432

ASP.NET Web API XmlFormatter does not work, falls back to JsonFormatter

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 <strong>UseXmlSerializer</strong> 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.

<strong>Update:</strong> 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)

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

Answer1:

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);

Recommend

  • DataGridView doesn’t allow user to Delete Row
  • Controlling WCF Message Body serialization
  • How to hide an item in datalist
  • C# How to handle polymorphic models using NSwag
  • 'Object.ReferenceEquals' is always false because it is called with a value type
  • DataContract surrogate for amplified value type
  • ObservableCollection and CollectionChanged event as WCF datacontract
  • Unable to load related entities in a WCF service
  • Entity Framework 6 connection string dll app config
  • dll not loading in python
  • Creating multiple dialogs in an MFC app with no main Window, they become children of each other
  • how to import a dll into a asp.net web application running on webserver
  • Where can I get runkit DLL extensions for PHP 5.3+?
  • FluentMigrator Failed Migrations Don't Rollback?
  • Window screenshot using WinAPI
  • What dll is needed for Windows.Devices.Geolocation?
  • Microsoft Chart Controls for Microsoft .NET Framework 4.0
  • How to add System.Windows dll to Visual Studio 2010 express?
  • How to write string.Contains(someText) in expression Tree
  • Send multimedia commands
  • What is the Linux Equivalent of Kernel32.dll?
  • DependencyObject.AssociatedObject is always null
  • CS1703: In Xamarin.Droid, should I use the .Net Standard windowsruntime.dll located in Mono.Framewor
  • when does setTimeout start executing in a inline
  • Deploying a CodeRush plugin from the Community Site
  • Available space left on drive - WinAPI - Windows CE
  • How do I register classes by both interface and namespace with Windsor?
  • Translating C# to PowerShell in InterIMAP
  • Very simple C++ DLL that can be called from .net
  • ilmerge with a PFX file
  • Turn off referential integrity in Derby? is it possible?
  • Add sale price programmatically to product variations
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • How to Embed XSL into XML
  • UserPrincipal.Current returns apppool on IIS
  • Unable to use reactive element in my shiny app
  • Conditional In-Line CSS for IE and Others?
  • java string with new operator and a literal
  • How do I use LINQ to get all the Items that have a particular SubItem?