Content negotiation to return HTML

cvbarros picture cvbarros · Jan 30, 2014 · Viewed 12.1k times · Source

After reading this blog post on how to return HTML from Web API 2 using IHttpActionResult, I wanted to somehow "wire-up" this IHttpActionResult to my ApiController based on the Accept header that is sent with request.

Given controller actions that have signature similar to this:

public MyObject Get(int id)
{
    return new MyObject();
}

If the request specifies the Accept: text/html, this IHttpActionResult should be used to return HTML. Is that possible? In addition, some insight on how this content negotiation pipeline works for json or xml (that have built-in support) would be greatly appreciated.

Answer

Kiran Challa picture Kiran Challa · Jan 31, 2014

If we keep the discussion of IHttpActionResult aside for a momment, Content-negotiation process in Web API is driven through formatters. So you would need to create a new formatter for handling the media type text/html.

Web API exposes the default algorithm it uses for content-negotiation called DefaultContentNegotiator which is an implementation of the service IContentNegotiator.

Now this negotiation algorithm can be run either by Web API automatically for you like in the following cases:

Usage # 1:

public MyObject Get(int id)
{
   return new MyObject();
}

OR

you can manually run the negotiation yourself like in the following:

Usage #2 :

public HttpResponseMessage Get()
{
    HttpResponseMessage response = new HttpResponseMessage();

    IContentNegotiator defaultNegotiator = this.Configuration.Services.GetContentNegotiator();
    ContentNegotiationResult negotationResult = defaultNegotiator.Negotiate(typeof(string), this.Request, this.Configuration.Formatters);

    response.Content = new ObjectContent<string>("Hello", negotationResult.Formatter, negotationResult.MediaType);
    return response;
}

Regarding IHttpActionResults:
In the following scenario, Ok<> is a shortcut method for generating an instance of type OkNegotiatedContentResult<>.

public IHttpActionResult Get()
{
    return Ok<string>("Hello");
}

The thing is this OkNegotiatedContentResult<> type does similar thing as in Usage # 2 scenario above. i.e they run the negotiator internally.

So to conclude, if you plan to support text/html media type then you need to write a custom formatter and add it to Web API's formatter collection and then when you use Ok<string>("Hello") with an Accept header of text/html, you should see the response in text/html. Hope this helps.