devlin carnate
devlin carnate

Reputation: 8591

How to iterate over object sent via AJAX JSON

I have the following JavaScript object:

var parameters = { "parameters" :
    [
        {
            "key": "feedbackSource",
            "value": "foo"
        }, {
            "key": "status",
            "value": "foo"
        }, {
            "key": "feedbackType",
            "value": "foo"
        }
    ]
};

console.log(JSON.stringify(parameters)) shows:

{"parameters":[{"key":"feedbackSource","value":"foo"},{"key":"status","value":"foo"},{"key":"feedbackType","value":"foo"}]}

AJAX:

$.ajax({
    type: "POST",
    url: "myPage.aspx/MyMethod",
    data: JSON.stringify(parameters),
    contentType: "application/json; charset=utf-8",
    dataType: "json"
});

Method:

[WebMethod]
public static void MyMethod(object parameters)
{

}

Question: How do I iterate over that object in C# to get the contents?

I have tried:

foreach (var p in (IEnumerable) parameters)
{
    foreach (var x in (IEnumerable) p)
    {
        var test = x;
    }
}

But test on the first iteration is a Key Value pair, with Key = "key" and Value = "feedbackSource". On the second iteration, Key = "value" and Value = "foo"

And that doesn't seem like the correct way to iterate over the object. I would expect the Key = "feedbackSource" and Value = "foo".

Upvotes: 0

Views: 181

Answers (2)

Geoff James
Geoff James

Reputation: 3180

"How do I iterate over that object in C# to get the contents"

After a good discussion with @Devlin about this - the following conclusion has been reached:

Current JSON data structure

The JSON string that is being generated (from the page) is a little confusing to say the least.

The existing data structure of

{ "parameters" : [ { "key": "feedbackSource", "value": "foo" }, { "key": "status", "value": "foo" }, { "key": "feedbackType", "value": "foo" } ] };

Was very confusing and obfuscated the data somewhat - making it very hard to traverse and iterate the objects inside.

It appeared to be of key:(key/value) pairs/pairs (wait, what?)

I proposed to structure a proper key/value pair structure to the JSON firstly (from within the page).

Like so:

{ "parameters" : 
    [ 
        { 
            "feedbackSource" : "foo" 
        }, 
        { 
            "status" : "foo" 
        }, 
        { 
            "feedbackType" : "foo" 
        } 
    ] 
} 

What is the ModelBinder doing?

As per @Devlin's screenshot: debug screenshot

The ModelBinder was cleverly assiging parameter as a Dictionary<string, object>, because it recognised the JSON as key/value pairs - in which the values were yet again key value pairs.

Obviously, every type in C# derives from object, so accepting this was just boxing it in an object.

Thus why other suggestions of casting to a string weren't successful.

ASP.NET has a ModelBinder which is able to detect types of objects passed to methods, to make it easier when getting data out in the method.


Passing in/using the right type

Suggestion 1

Cast the object parameter in the MyMethod signature to a Dictionary<string, string> (do it safely, where possible)

Like so:

var paramsDict = parameters as Dictionary<string, object>;
if (paramsDict != null)
{
    // Iterate over the dictionary in here
}

Suggestion 2

Seeing as we know that the object parameters is already of type Dictionary<string, object> (thanks to some wizardry by the ModelBinder), we could just use this type in the MyMethod signature, instead.

Like this:

[WebMethod]
public static void MyMethod(Dictionary<string, object> parameters)
{
    // Iterate in here
}

Iterating the data

Now that you've got a nice and easy to use Dictionary<string, object>, it is simple to iterate over it and grab the values from there.

Like this:

foreach (var param in paramsDict) // or "... in parameters" if you're using suggestion 2
{
    var key = param.Key;
    var value = param.Value;

    // Manipulate/persist the data
}

It's up to you how you then manipulate/persist the data, but this should give you a starting point of getting the data from your JSON object.

Summary

  • Change your JSON structure to be "proper" key/value pairs
  • Default ModelBinder is able to assign the JSON as a C# Dictionary<string, object>
  • Either change the MyMethod signature to accept Dictionary<string, object> type for parameter, or cast the parameter object to a Dictionary (both should work the same)
  • Iterate each item in the Dictionary. You can then access the Keys and Values of each item, and then manipulate the data however you wish

Furthermore
Given that your JSON string is passing in key/value pairs of string and string, I suspect that you may safely use Dictionary<string, string> to be picked up by the ModelBinder, or when casting etc. confirmation may be needed on this, however

Hope this helps, and best of luck in your project! :)

Upvotes: 1

Nagaraj Raveendran
Nagaraj Raveendran

Reputation: 1220

var parameters =
            {
                "parameters":
                [
                    {"feedbackSource": "foo", "status": "foo", "feedbackType": "foo"}
                ]
            };

create below class

public class mComputedProp
{
    public string feedbackSource { get; set; }
    public string status { get; set; }
    public string feedbackType { get; set; }
}

public class mcomputedprops
    {
        [JsonProperty("parameters")]
        public List<mComputedProp> mprops = new List<mComputedProp>();
    }

Modify your ajax call

$.ajax({
                type: "POST",
                url: '@Url.Action("getComputedProperty", "Home")',
                contentType: "application/json; charset=utf-8",
                async: false,
                dataType: "json",
                data: JSON.stringify({ listjson: JSON.stringify(parameters) })                    
            });


[WebMethod]
    public void getComputedProperty(string listjson)
        {
            mcomputedprops mod = JsonConvert.DeserializeObject<mcomputedprops>(listjson);
            string asdf = mod.mprops[0].feedbackSource.ToString();
        }

Upvotes: 1

Related Questions