trembler2003
trembler2003

Reputation: 567

Web Api call not returning __type in JSON response

We have an MVC website that was calling through to WCF Restful services but we are now replacing them with Web Api calls. The problem is that existing code in some of the MVC controllers is relying on the "__type" attribute being returned for each object in the JSON so it can do different things depending on the type of the object.

However, in the new Web Api responses, each of the objects returned don't have the "__type" entries in the JSON so the code is failing.

Does anyone know how this is done? I've found plenty about removing the __type entries for WCF services but nothing yet for making sure they're in for Web Api.

Upvotes: 1

Views: 2033

Answers (2)

Drew Marsh
Drew Marsh

Reputation: 33379

The __type field is a feature of the DataContractJaonSerializer (DCJS), specifically it is there for ASP. NET AJAX compatibility for endpoints that are configured with the enableWebScript behavior applied. Even more specifically this feature is controlled by setting the DataContractSerilizerSettings::EmitTypeInformation property to AsNeeded or Always.

Out of the box WebAPI is bound to use JSON.NET as its formatter for JSON media and, while it does support a similar concept with its TypeNameHandling feature, it is not wire compatible with DCJS.

Now you can switch WebAPI to use DCJS quite easily like so:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;

However that still won't help you because the DCJS instances they create internally in those cases are not configured with EmitTypeInformatiom which means they default to None.

Therefore, the only solution to get what you want is to write your own MediaTypeFormatter subclass which creates/configures its DCJS instances with the EmitTypeInformation setting you want and then register that to handle the JSON media types instead of the built in JsonMediaTypeFormatter. Luckily since ASP. NET web API is open source you should be able to copy the existing implementation and tweak it quite easily to suit this specific case.

Upvotes: 4

trembler2003
trembler2003

Reputation: 567

I found the answer after more Google'ing.

On the WebApi controller project side, in the Global App_Start function I added:

config.Formatters.JsonFormatter.SerializerSettings.TypeNameHandling = TypeNameHandling.Objects;

And then on the client C# side when I'm about to deserialized, I added:

JsonSerializerSettings settings = new JsonSerializerSettings();
settings.TypeNameHandling = TypeNameHandling.Objects;

So essentially, it's TypeNameHandling.Objects setting for the serializer which will put out $type for each object instead of __type but it still all works for me.

Upvotes: 1

Related Questions