Setting JSON formatter as default when no Accept header is sent?

Topics: Web Api
Jan 10, 2012 at 2:10 PM

I'm having some problems with forcing the JSON formatter being the default fallback method.  I'm supporting both JSON and XML media types, but I want the JSON formatter to be the default fallback.
I've managed to make it work when the Accept header is set to */* or empty (but header still present), but when the header is missing the XML formatter kicks in!

I've tried all kinds of tricks mentioned in discussion threads on this forum, including inserting the formatter at 0 and this snippet:

JsonMediaTypeFormatter jsonDefault = config.Formatters.JsonFormatter;
config.Formatters.Remove(jsonDefault);
config.Formatters.Insert(0, jsonDefault)

The only fix I can think of right now is to add a handler that adds a Accept header when none is present, but it would be nice to be able to control this somehow :)  Is the WebApi hardcoded to fallback to the XML formatter?

Jan 10, 2012 at 3:43 PM
Edited Jan 10, 2012 at 3:46 PM

Could this be a defect in the Web API Test Client? I now notice if I remove the Accept header its adding this by default:
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

Edit: This seems to be default browser behavior, or something in the Javascript libraries.  My code works correctly if there is no actual header sent.

Jan 17, 2012 at 9:25 PM

I have a solution to this that I found on the net, sorry I can't give credit because I lost the link.

What you can do, is change it so that you change the "Default" and only accept certain content types, otherwise it defaults.
This makes it so browsers are supported defaulted as JSON (what I made it for). 

 

    public class ForceJsonMessageHandler : DelegatingHandler
    { 
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (ShouldForceJson(request))
            {
                request.Headers.Accept.Clear(); //clear the accept and replace it to use JSON.
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            }
            return base.SendAsync(request, cancellationToken);
        }
 
        public static bool ShouldForceJson(HttpRequestMessage request)
        {
            if (request.Headers.Accept.Contains(new MediaTypeWithQualityHeaderValue("application/xml")))
                return false;
            return true;
        }
    }