If you’ve worked with JSON endpoints and WebAPI, you know how seamlessly it works when sending out objects that will be serialized into JSON. An example would be something like this:

public class Account
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Fullname { get { return FirstName + " " + LastName; } }     
}

public class AccountsController : ApiController
{
    public object Get()
    {
        return new Account {FirstName = "John", LastName = "Doe", AccountNo = 777};
    }
}

And when you issue a request with accept header of application/json, you’ll get this:

{
    FirstName: "John"
    LastName: "Doe"
    Fullname: "John Doe"
}

Which is all good and dandy. In our case, however, the object we were trying to work with was behaving differently. We didn’t have the source code for that object either, but the only difference we could pick was this:

{
    k__BackingField: "John"
    k__BackingField: "Doe"
}

What the….? Two issues here, if you’ve missed it. The name of the properties are totally messed up and the readonly property is not even serialized. The second issue was actually a default behavior when WebAPI was in beta versions, but it should work out of the box with the released / latest versions which we were using. And could really a SerializableAttribute make that big a difference?

Trying to serialize the object that had the SerializableAttribute with json, we could see that the outcome is as expected:

JsonConvert.SerializeObject(new Account {FirstName = "John", LastName = "Doe"}); // <- This worked fine

So what’s the issue? Isn’t Newtonsoft JSON library used in WebAPI out of the box?

The solution

After some digging, it turns out that WebAPI in fact is not using the DefaultContractResolver from Newtonsoft.Json library directly, but rather a customized one, although slightly. The one used by the WebAPI out of the box is System.Net.Http.Formatting.JsonContractResolver class. If you have a peek through the code, you’ll see something interesting.

public class JsonContractResolver : DefaultContractResolver
{
    public JsonContractResolver(MediaTypeFormatter formatter)
    {
        IgnoreSerializableAttribute = false;
    }
}

That’s suspiciously related to what seems to be our issue here, isn’t it? So the solution was to derive from JsonContractResolver and set that flag to true!

public class CustomContractResolver : System.Net.Http.Formatting.JsonContractResolver
{
    public CustomContractResolver() : base(new JsonMediaTypeFormatter())
    {
        IgnoreSerializableAttribute = true;
    }
}

The reasoning

This behavior apparently has introduced in JSON.NET version 4.5. From this version, the fields are serialized instead of properties but there are a couple of ways to change this behavior depending if you have access to the source code of not. You can read more about it here.