I am trying to post an object with nested objects and it doesn't Deserialize the internal objects.
Here is a simple example of the Xml I am trying to post.
<?xml version="1.0" encoding="utf-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomerId>100</CustomerId>
<Orders>
<Order><OrderId>1</OrderId><Amount>1</Amount></Order>
<Order><OrderId>2</OrderId><Amount>2</Amount></Order>
</Orders>
</Customer>
Here is my Customer model.
public class Customer
{
public Customer()
{
Orders = new List<Order>();
}
public string CustomerId { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public string OrderId { get; set; }
public int Amount { get; set; }
}
In my action, the CustomerId field is set to 100 but the Orders is empty. I did some debugging and I noticed that OnReadFromStreamAsync tries to deserialize this as a IKeyValueModel instead of Customer.
If I set the Content-Type to application/json then it works.
Anyway, I ended up writing my own MediaTypeFormatter and removed the default XmlFormatter. This can't be the right approach right?
One workaround is to try to opt-out of the model binding of the parameter and use the direct deserialization model. This can be done by using a IRequestContentReadPolicy. Say your action is called 'Post':
public class ReadAsSingleObjectPolicy : IRequestContentReadPolicy
{
public RequestContentReadKind GetRequestContentReadKind(HttpActionDescriptor actionDescriptor)
{
// deserialization model
if (actionDescriptor.ActionName.Equals("Post"))
{
return RequestContentReadKind.AsSingleObject;
}
else // default model binding
{
return RequestContentReadKind.AsKeyValuePairs;
}
}
}
Here is how you can add this IRequestContentReadPolicy in the config:
config.ServiceResolver.SetService(typeof(IRequestContentReadPolicy), new ReadAsSingleObjectPolicy());
We'll try to fix this in the next release so that this scenario would just work.
Thanks Maggie Ying and Hongmei Ge for the solution. Both of your answer work. Well, they are pretty much the same answer. :) I marked Maggie solution as the answer since it came first.
Anyway, I knew there must be a better way to solve the problem than my clumsy way.
ConradTran
Member
3 Points
2 Posts
Can't get the default XmlSerializer to support complex object
Feb 22, 2012 11:50 PM|LINK
I am trying to post an object with nested objects and it doesn't Deserialize the internal objects.
Here is a simple example of the Xml I am trying to post.
<?xml version="1.0" encoding="utf-8"?>
<Customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<CustomerId>100</CustomerId>
<Orders>
<Order><OrderId>1</OrderId><Amount>1</Amount></Order>
<Order><OrderId>2</OrderId><Amount>2</Amount></Order>
</Orders>
</Customer>
Here is my Customer model.
public class Customer
{
public Customer()
{
Orders = new List<Order>();
}
public string CustomerId { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public string OrderId { get; set; }
public int Amount { get; set; }
}
In my action, the CustomerId field is set to 100 but the Orders is empty. I did some debugging and I noticed that OnReadFromStreamAsync tries to deserialize this as a IKeyValueModel instead of Customer.
If I set the Content-Type to application/json then it works.
Anyway, I ended up writing my own MediaTypeFormatter and removed the default XmlFormatter. This can't be the right approach right?
Thanks,
Conrad
maggie.ying
Member
183 Points
39 Posts
Microsoft
Re: Can't get the default XmlSerializer to support complex object
Feb 23, 2012 12:28 AM|LINK
One workaround is to try to opt-out of the model binding of the parameter and use the direct deserialization model. This can be done by using a IRequestContentReadPolicy. Say your action is called 'Post':
public class ReadAsSingleObjectPolicy : IRequestContentReadPolicy { public RequestContentReadKind GetRequestContentReadKind(HttpActionDescriptor actionDescriptor) { // deserialization model if (actionDescriptor.ActionName.Equals("Post")) { return RequestContentReadKind.AsSingleObject; } else // default model binding { return RequestContentReadKind.AsKeyValuePairs; } } }Here is how you can add this IRequestContentReadPolicy in the config:
We'll try to fix this in the next release so that this scenario would just work.
Thanks,
Maggie Ying
Hongmei Ge
Member
26 Points
8 Posts
Microsoft
Re: Can't get the default XmlSerializer to support complex object
Feb 23, 2012 12:30 AM|LINK
You can switch the xml formatter to use the serializer to deserialize the request body by doing the following.
private class ReadAsSingleObjectPolicy : IRequestContentReadPolicy
{
public RequestContentReadKind GetRequestContentReadKind(HttpActionDescriptor actionDescriptor)
{
return RequestContentReadKind.AsSingleObject;
}
}
// here the config could be HttpSelfHostConfiguration or HttpConfiguration from web host case
config.ServiceResolver.SetService(typeof(IRequestContentReadPolicy), new ReadAsSingleObjectPolicy());
Please let me know if this works for you.
ConradTran
Member
3 Points
2 Posts
Re: Can't get the default XmlSerializer to support complex object
Feb 23, 2012 12:49 AM|LINK
Thanks Maggie Ying and Hongmei Ge for the solution. Both of your answer work. Well, they are pretty much the same answer. :) I marked Maggie solution as the answer since it came first.
Anyway, I knew there must be a better way to solve the problem than my clumsy way.
skippyfire
Member
34 Points
31 Posts
Re: Can't get the default XmlSerializer to support complex object
Feb 24, 2012 03:48 PM|LINK
Just a public service announcement related to this post. Henrik fixed the JSON .NET Formatter and it seems to work well with the complex types.
If you don't need XML you can use JSON. I like JSON better anyway.
akber007
Member
6 Points
7 Posts
Re: Can't get the default XmlSerializer to support complex object
Mar 29, 2012 06:34 PM|LINK
Hey Maggie,
After implementing, the solution you have given, its giving me internal server error. Could you suggest me something better.
Thanks
Akber
akber007
Member
6 Points
7 Posts
Re: Can't get the default XmlSerializer to support complex object
Apr 09, 2012 09:41 AM|LINK
It's not working at all. Do any body have idea, where it could be going wrong.
Thanks