Maksim Vi.
Maksim Vi.

Reputation: 9235

WebApi: */* media type handling

In my application I'm making some javascript requests to my Api Controllers to get some html formatted strings. When those requests are made with Accept: */* HTTP header (jQuery $.get method), so by default JsonMediaTypeFormatter is used and the data is returned with Content-Type: application/json in JSON format.

What I would like is to handle */* requests as text/html. So I tried to create a custom MediaTypeFormatter that supports */* media type, but it gives me the following error

The 'MediaTypeHeaderValue' of */* cannot be used as a supported media type because it is a media range.`

Alternatively I could always provide correct expected data types in my requests, but I'm curious if there's a way to handle */* media types.

Upvotes: 3

Views: 2482

Answers (2)

Kiran
Kiran

Reputation: 57989

The above behavior is due to the following:

The default con-neg algorithm in Web API has the following precedence order of choosing the formatter for response:

  1. Formatter match based on Media Type Mapping.
  2. Formatter match based on Request Accept header's media type.
  3. Formatter match based on Request Content-Type header's media type.
  4. Formatter match based on if it can serialize the response data’s Type.

Now, JsonMediaTypeFormatter comes with a built-in media type mapping called XmlHttpRequestHeaderMapping which inspects an incoming request and sees if the request has the header x-requested-with: XMLHttpRequest and also if there is no accept header or if the Accept header is only having */*.

Since your request is mostly probably looking like below, according to the precedence order JsonMediaTypeFormatter is chosen as the one writing the response:

GET /api/something
Accept: */*
x-requested-with: XMLHttpRequest

A solution for your issue would be is to explicitly ask for "text/html" as this is what you are expecting.

GET /api/something
Accept: text/html
x-requested-with: XMLHttpRequest

Couple of very old blog posts about Content negotiation that I wrote: http://blogs.msdn.com/b/kiranchalla/archive/2012/02/25/content-negotiation-in-asp-net-mvc4-web-api-beta-part-1.aspx
http://blogs.msdn.com/b/kiranchalla/archive/2012/02/27/content-negotiation-in-asp-net-mvc4-web-api-beta-part-2.aspx

Upvotes: 7

Youssef Moussaoui
Youssef Moussaoui

Reputation: 12395

Great question.

You can't set */* to be a supported media type, but what you can do is set your formatter to be the first one. Web API will pick the first formatter in the formatter collection that can write out the type if there is no Accept header or if the Accept header is */*.

So you'd want to configure your Web API like this:

config.Formatters.Insert(0, new MyHtmlFormatter());

Upvotes: 2

Related Questions