Search code examples
c#asp.netasp.net-web-apiodataasp.net-mvc-5

Dictionary<string, object> serialization in OData using ASP.Net MVC 5 and Web API 2.0


I am using OData services over the new Web API for MVC 5 and I am experiencing some problems.

I have followed this tutorial to start develop OData services and almost everything is right. The project builds, the routes work, and the URLs is working great.

One of my classes is called Post and have a property of type Dictionary<string, object> named Parameters, like below:

public partial class Post : IPost
{
    public Guid Id { get; set; }

    public string Author{ get; set; }  
    public string Content{ get; set; }  
    public DateTime PostedDate{ get; set; }  
    public List<Photo> Pictures { get; set; }  

    public Dictionary<string, object> Parameters { get; set; }  
}

The URL to list all the Post objects (http://localhost/odata/Posts) is working fine when I perform a get request in browser. All the objects are successfully serialized.

But importing the OData Metadata as a Service Reference in another application, when I get the list of Post entities, I get the error below:

An exception of type 'System.InvalidOperationException' occurred in Microsoft.Data.OData.dll but was not handled in user code

Additional information: The type 'WebApplication1.ServiceReference2.System.Collections.Generic.KeyValuePair_2OfString_Object' has no settable properties.

How to resolve this problem for import Service References with success?


Solution

  • Some days later I tried a lot of different tests.

    • Dictionary<string, object> => throw the original error
    • Dictionary<string, string> => same error
    • List<KeyValuePair<string, object>> => same error
    • List<KeyValuePair<string, string>> => same error

    I realized the KeyValuePair class was the problem, but I didn't know why.

    So, I created a class named Parameter like below:

    public class Parameter
    {
        public string Key { get; set; }
        public string Value { get; set; }
    }
    

    ...I changed the list type to List<Parameter> and it worked!

    After thinking more about the problem, I realized one important sentence in the error:

    'WebApplication1.ServiceReference2.System.Collections.Generic.KeyValuePair_2OfString_Object' has no settable properties

    The dictionaries are nothing more than lists of KeyValue pairs, and the KeyValuePair<TKey, TValue> struct have two properties, named "Key" and "Value", which have only get accessors. So, they are readonly.

    We may conclude the OData Service Reference can't deserialize the readonly properties, by some reason I don't know yet.

    My workaround worked, but I am wondering if the Service Reference may have someday a reflection way to set this properties.