1

I'm trying to work out how to extract a List of objects from a JSON request in a WEBAPI call. Within this list of objects is a Dictionary object, a List object and a List> object.

My request from my MVC controller, looks a bit like this:

//Gets a list of various objects
List<object> values = new List<object>(); 
values.add(GetItem1()); //Returns a Dictionary<string, string> object
values.add(GetItem2()); //Returns a List<string> object
values.add(GetItem3()); //List<KeyValuePair<string, string>> 

var content = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json");
HttpResponseMessage postResult = client.PostAsync(baseURL, content).Result;

In the WEBAPI object, I have this function that is receiving the call from the MVC controller. This is where I have my trouble, I can't get the data out of the List. The first item in the list, happens to be a Dictionary.

[HttpPost]
public void LogError(List<object> myObjectList)
{
    Dictionary<string, string> items = (Dictionary<string, string>)myObjectList[0];
    List<string> moreItems = (List<string>)myObjectList[1];
    List<KeyValuePair<string, string>> evenMoreItems = (List<KeyValuePair<string, string>>)myObjectList[2];
}

If I try to start using the object, I get the error:

Cannot cast 'myObjectList[0]' (which has an actual type of 'Newtonsoft.Json.Linq.JObject') to 'System.Collections.Generic.Dictionary<string,string>'

Unfortunately, I'm at a complete loss about what to do next. I can't seem to find a way to deserialize the List into these individual object types.

2 Answers 2

2

The reason why you are hitting the cast exception is because the type information is lost from the client and server.

One way to get your scenario to work is to do the following

  1. Use ObjectContent instead of StringContent so we let the formatter (i.e. JsonMediaTypeFormatter) to deal with the serialization and deserialization
  2. Turn on TypeNameHandling on both the client and server so that the type information will be send on the wire

Server (WebApiConfig.cs):

 config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;

Client:

        //Gets a list of various objects
        List<object> values = new List<object>();
        values.Add(GetItem1()); //Returns a Dictionary<string, string> object
        values.Add(GetItem2()); //Returns a List<string> object
        values.Add(GetItem3()); //List<KeyValuePair<string, string>> 

        var formatter = new JsonMediaTypeFormatter();
        formatter.SerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All;

        var content = new ObjectContent<List<object>>(values, formatter);
        HttpResponseMessage postResult = client.PostAsync(baseURL, content).Result;

Sample Request Body:

{"$type":"System.Collections.Generic.List1[[System.Object, mscorlib]], mscorlib","$values":[{"$type":"System.Collections.Generic.Dictionary2[[System.String, mscorlib],[System.String, mscorlib]], mscorlib","DictionaryKey1":"DictionaryValue1"},{"$type":"System.Collections.Generic.List1[[System.String, mscorlib]], mscorlib","$values":["ListItem1"]},{"$type":"System.Collections.Generic.List1[[System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib],[System.String, mscorlib]], mscorlib]], mscorlib","$values":[{"Key":"KeyValuePairKey","Value":"KeyValuePairKeyValue"}]}]}

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! This did the trick. I did have to add a deserialization step. Here is some sample code: Dictionary<string, string> parameters = JsonConvert.DeserializeObject<Dictionary<string, string>>(convertedObjectList[0].ToString());
0

I may be wrong but off the top of my head you cant have a

List[object]

as how will it know what the type is? You need to specify a concrete object of the type that is coming in?

Start with something simple:

public class TestClass
{
    public int Id { get; set; }
    public string Name { get; set; }
}

List values = new List(); values.Add(new TestClass() { Id = 1, Name = "test1" }); values.Add(new TestClass() { Id = 12, Name = "test2" });

var content = new StringContent(JsonConvert.SerializeObject(values), Encoding.UTF8, "application/json");
HttpResponseMessage postResult = client.PostAsync(baseURL, content).Result;

receiving webapi method:

public void LogError(List<TestObject> myObjectList)
{ // breakpoint here and see what myObjectList contains

}

6 Comments

Well, when I debug the WEPAPI, I can see all the data and it all looks about right: But as soon as I try to cast it, (see the 2nd code block), everything blows up. That's where I'm stuck
I think you may struggle to cast directly into a dictionary, you will probably have to loop through the List and repopulate the Dictionary yourself.
Have you tried using Dictionary<string, string> as the parameter on the controller method?
Just to be clear, the list of objects has a variety of different objects in it (don't ask). The first one is of type Dictionary<string, string>, the 2nd is a list<string> and the 3rd is a List<KeyValuePair<string, string>> object.
Doubt its going to be able to work that out. I think you would be better wrapping these into a class and then defining that class as the method parameter.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.