Troubleshooting serialization problems in Web API

Published on August 10, 2012

I see many questions on Stackoverflow and the MSDN forums where people are having difficulty because the objects they are trying to return from there API are not being serialized as they expect.  Consider you have an API action that looks like this:

public Foo GetFoo() {   

var foo = new Foo();
return foo; }

What are you supposed to do to debug what is going wrong here when your Foo just isn’t serializing as you expect?  You could setup a trace writer as is demonstrated by Mike Wasson here. That will show you some very useful information, but maybe not enough.

It is handy to know that the above action is functionally equivalent to the following,

public HttpResponseMessage Get() {
   
   // Create the object to return
   var foo = new Foo();

   // Get the default ContentNegotiation service
   var negotiator = Configuration.Services.GetService(typeof (IContentNegotiator))                                                            as IContentNegotiator;

   // Negotiate the appropriate formatter based on the request and available formatters
   var negotiationResult = negotiator.Negotiate(typeof (Foo), Request,                                                  Configuration.Formatters);

   // Create an ObjectContent that is used to create the HTTP payload
   var content = new ObjectContent<Foo>(foo, negotiationResult.Formatter);
   content.Headers.ContentType = negotiationResult.MediaType;

   //Force the ObjectContent to serialize the Foo using the Formatter
   content.LoadIntoBufferAsync().Wait();
   
   // Return a HttpResponseMessage with the Content
   return new HttpResponseMessage {Content = content};
}

The advantage of this method is you can breakpoint and identify what formatter is being selected and you can see the Content object before it is returned.  Forcing the content to LoadIntoBuffer before returning allows you to see if a failure occurs during serialization.

If you identify that the correct formatter is being used then you can isolate the problem down in a simple test:

[Fact]
public void TestSerialization() {

    var foo = new Foo();

    var formatter = new JsonMediaTypeFormatter();

    var content = new ObjectContent<Foo>(foo, formatter);
    var result = content.ReadAsStringAsync().Result;

    Assert.Equal("{}",result);
}

My guess is that 4 out of 5 times, the problem has nothing to do with the Web API framework at all, but is a limitation of the underlying serializer/parser used by the formatter class.