简体   繁体   中英

"Type System.String is not supported for deserialization of an array" error using JSON.stringify

In response to a button click, I collect some user supplied data and pass it to a web method to process.

When this mapping has simple variables, it works fine (int, string, etc.) but now I am adding two array of objects and running into problem. I get "Message:Type System.String is not supported for deserialization of an array". I am using JSON.Net, in a C# web application (VS 2017).

This is what I have so far:

var admins = [];
var departments = [];

At some point, these array will have a set of objects, like rows of departmentName, acronym or in case of "admins" will have rows of userID, lastName, etc.

$(document).on("click", "#btnAdd", function (event) {
    ...
    var newMapping = {
        orgName: orgName,
        orgAcronym: acronym,
        admins: admins,
        depts: departments
    }
    addNewOrg(newMapping, "oMapping");
    ...
});

function addNewOrg(newMapping, jsonObjName) {
    $.ajax({
        url: "../WebService/Blah.asmx/AddOrganization",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: "{" + jsonObjName + ":" + JSON.stringify(newMapping) + "}",  // This is where it throws up!
    }).done(function (result) {
        if (!result || result.d === "") {
        }
        else {
            var jResult = result.d;
            if (jResult == "-1") {
            }
            else {
            }
        }
    }).fail(function (jqXHR, textStatus, errorThrown) {
    });  
    return false;
}

Web method:

[WebMethod]
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)]

public string AddOrganization(Dictionary<string, string> oMapping)
{
    string JSONresult = string.Empty;
    var ErrorData = new object();

    if (oMapping.Count == 0)
        return JSONresult;

    Organization oOrg = new Organization();
    try
    {
        oOrg.OrganizationName = oMapping["orgName"].ToString();
        oOrg.Acronym = oMapping["orgAcronym"].ToString();

        //JSONresult = AddOrganization(oOrg);
    }
    catch (Exception ex)
    {
        ErrorData = new
        {
            Success = "false",
            Error = "Internal error: " + ex.Message
        };
        JSONresult = JsonConvert.SerializeObject(ErrorData);
    }
    return JSONresult;
}

Update:

When I trace the code using "debugger" and put a break point in "addNewOrg" function, I can see the "newMapping" contains:

orgName="Organization1"
orgAcronym="ORG1"
admins = [[object Object], [object Object]]  // I added two users
depts = [[object Object], [object Object]]   // I added two departments

then, when I check JSON.stringify(newMapping) it contains:

"{\"orgName\":\"ORGANIZATION1\",\"orgAcronym\":\"ORG1\",\"admins\":[{\"fn\":\"John\",\"mi\":\"\",\"ln\":\"Doe\",\"email\":\"John.Doe@blah.com\",\"userid\":\"ABCDE\",\"userType\":4},{\"fn\":\"Jane\",\"mi\":\"\",\"ln\":\"Doe\",\"email\":\"Jane.Doe@blah.com\",\"userid\":\"FGHIJ\",\"userType\":4}],\"depts\":[{\"dn\":\"Department1\",\"ac\":\"DPT1\"},{\"dn\":\"Department2\",\"ac\":\"DPT2\"}]}"

So, to me it doesn't look like JSON.Stringify is the culprit. But it skips "Done" and goes to "fail". I think it might be the web method signature of "Dictionary<string, string> oMapping".

Yes, the method signature is the problem. The JSON you had prior to adding admins and depts was a simple object where all the values were strings. Now that two of the values are arrays, it cannot be deserialized into a Dictionary<string, string> anymore. You could try changing it to Dictionary<string, object> , but really the better solution is to create Data Transfer Object (DTO) classes in C# to fit the data you are sending. The property names of your DTOs need to match the property names in the JSON you are sending. The class names can be whatever you want.

Something like this should work, based on your sample JSON:

public class OrgDTO
{
    public string orgName { get; set; }
    public string orgAcronym { get; set; }
    public List<AdminDTO> admins { get; set; }
    public List<DeptDTO> depts { get; set; }
}

public class AdminDTO
{
    public string fn { get; set;}
    public string mi { get; set; }
    public string ln { get; set; }
    public string email { get; set; }
    public string userid { get; set; }
    public int userType { get; set; }
}

public class DeptDTO
{
    public string dn { get; set; }
    public string ac { get; set; }
}

Then change your method signature to accept the "root" DTO, which is OrgDTO in this example:

public string AddOrganization(OrgDTO orgDto)
{
    ...
}

Obviously you will need to adjust the code inside the method as well since you will no be longer working with a Dictionary<string, string> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM