Question

I have been pulling my hair out for the past two days trying to figure out why XmlFormatter (via DataContractSerializer) does not serialize data I return in my Web API method. WebAPI decides to use JSON anyway but I need the result to be in XML (as per application that will use this API). I have setup my browser to send Accept: application/xml for the resolver to use the XmlFormatter (but the result is always json).

Controller:

public class MyController : ApiController
{
    public MyDataResultList GetData(string someArgument)
    {

        // magic here that gets the data
        MyDataResultList items = MyDataResultList.GetData(someArgument);

        return items;
    }
}

MyDataResultList is contained in a dll and has this similar layout:

[DataContract]
[CollectionDataContract(Name = "MyDataList")]
[KnownType(typeof(List<MyDataItem>))]
public class MyDataResultList : List<MyDataItem>
{

    [DataMember]
    public string SomethingHere
    {
        get;
        set;
    }

    [DataMember]
    public TimeSpan StartTime
    {
        get;
        set;
    }

    [DataMember]
    public TimeSpan StopTime
    {
        get;
        set;
    }

}

I have tried setting UseXmlSerializer to true, but I need to use the DataContractSerializer on the client end to de-serialize the results back correctly.

So the final question is, is it possible to configure web API to throw an exception if it is unable to serialize using whatever formatter comes first? I believe (in my opinion) it's very misleading and too abstractive to have it just silently fall back to JSON without giving me any clue as to what is causing that.

Update: manually serializing MyDataResultList using DCS throws InvalidDataContractException: Type 'MyDataResultList' with CollectionDataContractAttribute attribute is an invalid collection type since it has DataContractAttribute attribute. But the underlying question remains: how to get the Web API to throw this to me instead of silently falling back to JSON? (and making debugging more difficult)

Update2: DataContract serializer seems to skip SomethingHere/StartTime/EndTime properties entirely even though they have [DataMember] on them.

Was it helpful?

Solution

Your way of diagnosis is correct and yeah Web API's content negotiation process will try to find the best formatter based on bunch of logic(ex: Accept header if present, Content-Type header if Accept-Header not present, asks each formatter if it can serialize a type etc.).

You can disable this default behavior (i.e finding the first formatter in the list of formatters which can write/serialize a type) by doing the following. This will result in a 406 Not Acceptable response being generated:

DefaultContentNegotiator negotiator = new DefaultContentNegotiator(excludeMatchOnTypeOnly: true);
config.Services.Replace(typeof(IContentNegotiator), negotiator);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top