I'm implementing a Web API 2 service that uses JSON.NET for serialization.
When I try to PUT ( deseralize ) updated json data, the abstract class is not present meaning it didn't know what to do with it so it did nothing. I also tried making the class NOT abstract and just inheriting from it and then each PUT deseralized to the base class rather than the derrived class missing the properties of the derrived class.
Example:
public class People
{
// other attributes removed for demonstration simplicity
public List<Person> People { get;set; }
}
public abstract class Person
{
public string Id {get;set;}
public string Name {get;set;}
}
public class Employee : Person
{
public string Badge {get;set;}
}
public class Customer : Person
{
public string VendorCategory {get;set;}
}
with my web api configured to do typename handling:
public static void Register(HttpConfiguration config)
{
config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling =
TypeNameHandling.Objects;
}
then I PUT the JSON like:
{
people: [{
name: "Larry",
id: "123",
badge: "12345",
$type: "API.Models.Employee, API"
}]
}
to the web api method:
public HttpResponseMessage Put(string id, [FromBody]People value)
{
people.Update(value); // MongoDB Repository method ( not important here )
return Request.CreateResponse(HttpStatusCode.OK);
}
but the output when inspecting value
is always:
People == { People: [] }
or if non-abstract:
People == { People: [{ Name: "Larry", Id: "123" }] }
missing the inherrited property. Anyone ran into this problem and come up with anything?
The $type
function has to be the first attribute in the object.
In the above example I did:
{ people: [{ name: "Larry", id: "123", badge: "12345", $type: "API.Models.Employee, API" }] }
after moving $type
to the top like:
{ people: [{ $type: "API.Models.Employee, API", name: "Larry", id: "123", badge: "12345" }] }
the serializer was able to deseralize the object to the correct cast. Gotta love that!
I have tried your scenario now and it works fine. But I did notice that you are missing a ,
(comma) after the id
property in your json input.
I figured this out by using the following ModelState validity check in my action which then showed the error in my request payload. This could be useful to you too:
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, this.ModelState);
}
I know this post is old now and the answer has been marked, but I thought my solution might be helpful....
Try adding the JsonProperty attribute to the properties on your abstract class.
using JTC.Framework.Json;
...
public class People
{
// other attributes removed for demonstration simplicity
public List<Person> People { get;set; }
}
public abstract class Person
{
[JsonProperty()]
public string Id {get;set;}
[JsonProperty()]
public string Name {get;set;}
}
public class Employee : Person
{
public string Badge {get;set;}
}
public class Customer : Person
{
public string VendorCategory {get;set;}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With