简体   繁体   中英

Deserialize JSON to C# - Values from Checkboxes

I'm attempting to send form values over AJAX to a C# web service. Then, using JavaScriptSerializer.Deserialize, convert the JSON to a C# class. Below is the class:

[Serializable]
[DataContract(Name = "PostParameters")]
public class TagData
{
    public TagData()
    {
    }

    [DataMember(Name = "TargetId")]
    public string TargetId { get; set; }
    [DataMember(Name = "TargetType")]
    public string TargetType { get; set; }
    [DataMember(Name = "Tags")]
    public List<string> Tags { get; set; }
}

Here is the method being called:

[WebMethod]
public string UpdateTags(string PostParameters)
{
    JavaScriptSerializer serializer = new JavaScriptSerializer();
    var tagData = serializer.Deserialize<TagData>(PostParameters);
}

This works when more than one checkbox is checked. The Tags property is successfully populated. However, when less than two items are checked, there is a conversion error. The serializer cannot convert the single string value to a List object.

Here is how the JSON is sent with one checkbox checked: {"Tags":"14","TargetId":"36946","TargetType":"Officer"}

Here is how the JSON is sent with more than one checkbox checked: {"Tags":["12","5","2"],"TargetId":"36946","TargetType":"Officer"}

I attempted changing the Tags property in my C# class to a string array: public string[] Tags { get; set; } public string[] Tags { get; set; } public string[] Tags { get; set; } however, this resulted in the JSON not being mapped at all.

I also attempted adding [] to the checkbox input names like so: <input type="checkbox" name="tags[]" />

This sent the JSON across as so, with one checkbox checked: {"Tags[0]":"14","TargetId":"36946","TargetType":"Officer"}

and more than one checkboxes checked: {"Tags[0]":"14","Tags[1]":"19","TargetId":"36946","TargetType":"Officer"}

This seems like it would work with the string array property, but it won't map for either that or the List property. The Tags property will always be null because it's unable to map.

UPDATE - Here's where the JSON is generated

var params = $.toJSON({ 'PostParameters': JSON.stringify($inputs.serializeObject()) });

and here's the serializeObject() function:

serializeObject: function () {
    var obj = {},
    names = {};

    $.each(this.serializeArray(), function (i, o) {
        var n = o.name,
        v = o.value;

        if (n.includes('[]')) {
            names.n = !names.n ? 1 : names.n + 1;
            var indx = names.n - 1;
            n = n.replace('[]', '[' + indx + ']');
        }

        obj[n] = obj[n] === undefined ? v
          : $.isArray(obj[n]) ? obj[n].concat(v)
          : [obj[n], v];
    });

    return obj;    
}

Any help is appreciated.

edit you client side code to send an array of one element in case of one checkbox is selected
JSON with one checkbox checked:
{"Tags":["14"],"TargetId":"36946","TargetType":"Officer"}

I was able to solve this using Rick Strahl's example here: https://weblog.west-wind.com/posts/2010/Sep/07/Using-jQuery-to-POST-Form-Data-to-an-ASPNET-ASMX-AJAX-Web-Service

Essentially, create a NameValue class:

public class NameValue
{
    public string name { get; set; }
    public string value { get; set; }
}

Use these extension methods to get form values from the collection:

public static class NameValueExtensionMethods
{
    /// <summary>
    /// Retrieves a single form variable from the list of
    /// form variables stored
    /// </summary>
    /// <param name="formVars"></param>
    /// <param name="name">formvar to retrieve</param>
    /// <returns>value or string.Empty if not found</returns>
    public static string Form(this  NameValue[] formVars, string name)
    {
        var matches = formVars.Where(nv => nv.name.ToLower() == name.ToLower()).FirstOrDefault();
        if (matches != null)
            return matches.value;
        return string.Empty;
    }

    /// <summary>
    /// Retrieves multiple selection form variables from the list of 
    /// form variables stored.
    /// </summary>
    /// <param name="formVars"></param>
    /// <param name="name">The name of the form var to retrieve</param>
    /// <returns>values as string[] or null if no match is found</returns>
    public static string[] FormMultiple(this  NameValue[] formVars, string name)
    {
        var matches = formVars.Where(nv => nv.name.ToLower() == name.ToLower()).Select(nv => nv.value).ToArray();
        if (matches.Length == 0)
            return null;
        return matches;
    }
}

Post the data using JSON.stringify only:

data: JSON.stringify({ formVars: arForm })

and accepting a parameter to my web method as a NameValue array:

public string UpdatTags(NameValue[] formVars)

This works when multiple checkboxes are checked, a single checkbox is checked, or no checkboxes are checked.

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