Content negotiation to return HTML

asp.net-web-api, c#, content-negotiation, html

Solution

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.

Problem

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.

Original source