Question

I am trying to deserialize my JSON object and pass it as a model to my view. Since I don't know what properties the model will have, I have read that I should use an ExpandoObject.

Here is what I have tried:

public ActionResult Index()
{
    var myObj = new object();

    List<Dictionary<string, object>> container = new List<Dictionary<string, object>>()
    {
        new Dictionary<string, object> { { "Text", "Hello world" } }
    };
    JavaScriptSerializer json_serializer = new JavaScriptSerializer();
    myObj = json_serializer.DeserializeObject(json_serializer.Serialize(container));
    return View(myObj.ToExpando());
}

And, in the same namespace I have defined this class:

public static class Helpers
{
    public static ExpandoObject ToExpando(this object anonymousObject)
    {
        IDictionary<string, object> anonymousDictionary = new RouteValueDictionary(anonymousObject);
        IDictionary<string, object> expando = new ExpandoObject();
        foreach (var item in anonymousDictionary)
            expando.Add(item);
        return (ExpandoObject)expando;
    }
}

And, in my view I have this loop:

@foreach (var item in Model)
{
    @item.Text
}

When I run, I get this error:

'System.Collections.Generic.KeyValuePair' does not contain a definition for 'Text'

Upon debugging, the Model doesn't seem to have any public properties. When I look deep within the private members, I see the data that I want.

Why aren't these public properties such that I can access them?

Edit: Here you can see the expando object model that is getting passed to my view:

enter image description here

Note: The SyncRoot property seems to contain my object.

Edit: This is the deserialized object:

enter image description here

Was it helpful?

Solution 2

The solution for me was to do something like this (using the ExpandoObjectConverter):

var myObj = new object();

List<Dictionary<string, object>> container = new List<Dictionary<string, object>>()
{
    new Dictionary<string, object> { { "Text", "Hello world" } }
};
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
var converter = new ExpandoObjectConverter();
var obj = JsonConvert.DeserializeObject<IEnumerable<ExpandoObject>>(json_serializer.Serialize(container), converter);

return View(obj);

However, this doesn't account for deeply nested JSON objects. I can probably create some sort of recursive method.

It's sad that the framework doesn't support such an obvious requirement; unless I am missing something.

OTHER TIPS

Notice that @item is defined as a System.Collections.Generic.KeyValuePair based on your error.

These means that you have two properties: Key and Value.

Here are two possible solution:

@foreach (var item in Model.Values)
{
    @item.Id
}

or

@foreach (var item in Model)
{
    @item.Value.Id
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top