Jeremy
Jeremy

Reputation: 46420

Web API content negotiated formatters with accept header and url parameter

I have implemented content negotiation so that a specific serializer will be used based on the accept header:

XmlFormatter fmtXml = new XmlFormatter();
fmtXml.SupportedMediaTypes.Add(new 
System.Net.Http.Headers.MediaTypeHeaderValue("text/xml"));

JsonFormatter fmtJson = new JsonFormatter();
fmtJson.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));


config.Formatters.Insert(0, fmtJson);
config.Formatters.Insert(0, fmtXml);

I need to allow a client to specify the desired format using a url parameter, which would take precedence over the accept header.

To do this, I've started subclassing the DefaultContentNegogiator (although I don't know that it's the best idea.:

public class CustomContentNegotiator : DefaultContentNegotiator
{
    public override ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
    {
        string sMimeType = HttpUtility.ParseQueryString(request.Url.Query).Get("_format");

        if (!string.IsNullOrEmpty(sMimeType))
        {
            ...
        }
        else
        {
            return base.Negotiate(type, request, formatters);
        }
    }
}

Then I replace the default content negotiator with mine:

GlobalConfiguration.Configuration.Services.Replace(typeof(IContentNegotiator), new CustomContentNegotiator());

The idea with the custom content negotiator is that if a content format has been specified as a url parameter, I would locate the formatter that matches, otherwise I would just fallback to the behavior of the DefaultContentNegotiator.

I'm just not sure how to match correctly on the supported media types, or if there is a better, simpler solution to this...

Upvotes: 0

Views: 182

Answers (1)

Jeremy
Jeremy

Reputation: 46420

I determined that using a custom content negotiator was a red herring. Instead I was able to use a MediaTypeMapping which matches against a specific url parameter instead of the accept request header:

fmtJson.MediaTypeMappings.Add(new System.Net.Http.Formatting.QueryStringMapping("_format", "json", "application/json"));

Upvotes: 0

Related Questions