Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Content negotiation to return HTML

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.

like image 798
cvbarros Avatar asked Jan 30 '14 21:01

cvbarros


People also ask

What are the different types of HTTP content negotiation?

There are two kinds of content negotiation which are possible in HTTP: server-driven and agent-driven negotiation. These two kinds of negotiation are orthogonal and thus may be used separately or in combination.

Which HTTP header is used for content negotiation?

The Accept header tells the server what formats or MIME types that the client is looking for. You can use the HTTP Accept headers to determine the content format used to exchange data. While the Accept header is not as visible as URLs or parameters, this header is a more flexible method of handling content negotiation.

How do I content negotiation in Web API?

In Web API, content negotiation is performed by the runtime (at the server side) to determine the media type formatter to be used based to return the response for an incoming request from the client side. Content negotiation is centered on Media type and Media type formatter.

What is content negotiation in DRF?

Content negotiation is the process of selecting one of multiple possible representations to return to a client, based on client or server preferences.


1 Answers

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.

like image 192
Kiran Avatar answered Oct 12 '22 18:10

Kiran