I have an API method from which I want to return either XML, HTML, plain text, or JSON. The data in question is not an object per-se so I can't just return an object to the framework and have it serialize for me. So I am returning a HttpResponseMessage from
the method with StringContent to specify the actual content to return.
My question is, how can I determine from within the API method which content type the client has requested? I'd like to avoid passing this as a custom parameter to the method because the other methods will use the built-in content type negotiation which
uses the Accept or Content-Type request headers. While I could just access the request headers directly, this seems wrong since content type negotiation can be influenced by other factors as well (such as media type mappings.)
Sorry if the question sounds unclear. I am very new to ASP.NET MVC and the Web API in particular.
There is a property called 'Request' which is available for every ApiController derived controller. This property will give you access to the current request from which you should be able to get the information about the headers you want. I am not sure if
i answered your question.
@kiran: That's what I was trying to avoid doing. I wanted to use the built-in content type negotiation and just get access to the decision. If I use the request headers directly, I'll be duplicating the effort and it wouldn't adapt with changes to the conneg
strategy.
@panesofglass: I'm already doing the serialization myself, but your sample (in addition to the library's source) has pointed me in the right direction. It doesn't look like it's going to be as straightforward as I thought since content negotiation apparently
isn't performed at all until a serializable object is returned. Since I'm handling the serialization, looks like I have to do the content type negotiation as well.
I wanted to use the built-in content type negotiation and just get access to the decision
May be you are looking this,
public class MyFormatterSelector : FormatterSelector
{
protected override MediaTypeFormatter OnSelectWriteFormatter(Type type, FormatterContext formatterContext, IEnumerable<MediaTypeFormatter> formatters, out MediaTypeHeaderValue mediaType)
{
var m = base.OnSelectWriteFormatter(type, formatterContext, formatters, out mediaType);
return m;
}
protected override MediaTypeFormatter OnSelectReadFormatter(Type type, FormatterContext formatterContext, IEnumerable<MediaTypeFormatter> formatters)
{
var m = base.OnSelectReadFormatter(type, formatterContext, formatters);
return m;
}
}
GlobalConfiguration.Configuration.ServiceResolver.SetService(typeof(IFormatterSelector), new MyFormatterSelector());
"And whoever is removed away from the Fire and admitted to Paradise, he indeed is successful." (The Holy Quran)
Excellent Windows VPS Hosting Imran Baloch MVP, MVB, MCP, MCTS, MCPD
Marked as answer by Mike Stall on Apr 20, 2012 10:05 PM
FWIW, FormatterSelector has been changed and renamed to IContentNegotiator. But you can still get it and explicitly invoke this method:
Thanks But I think Current Official Build(not talking about current source) does not have IContentNegotiator. BTW, Thanks for letting us.
"And whoever is removed away from the Fire and admitted to Paradise, he indeed is successful." (The Holy Quran)
Excellent Windows VPS Hosting Imran Baloch MVP, MVB, MCP, MCTS, MCPD
Is this just for a single request or for all of your requests in the API?
If it's just for a single request it's probably easiest to just case block your output based on the specified option. You can then use the appropriate Request headers to examine the requested accept headers and decide what to do. Alternately (in post beta
builds) you can use Request.CreateResponse() to create the Response object with the conneg matched output message type.
I think the latter is probably not going to work well if you are returning non-fixed formats like HTML strings etc., but you can create the response and check if it's XML/JSON and then use that or create a new Response object for the non-internally supported
output types like html. If all your requests require this you should probably create a custom output Formatter that handles all the output types you're creating in one place. You then can check the accept headers in there and create the appropriate response.
Frankly though if all your requests do this then you're not taking great advantage of what the API offers (other than routing) really and you might be better off just creating a custom Http Handler, which might just be more straight forward.
josheinstein
0 Points
3 Posts
HttpResponseMessage that plays nice with content negotiation
Mar 28, 2012 06:26 PM|LINK
I have an API method from which I want to return either XML, HTML, plain text, or JSON. The data in question is not an object per-se so I can't just return an object to the framework and have it serialize for me. So I am returning a HttpResponseMessage from the method with StringContent to specify the actual content to return.
My question is, how can I determine from within the API method which content type the client has requested? I'd like to avoid passing this as a custom parameter to the method because the other methods will use the built-in content type negotiation which uses the Accept or Content-Type request headers. While I could just access the request headers directly, this seems wrong since content type negotiation can be influenced by other factors as well (such as media type mappings.)
Sorry if the question sounds unclear. I am very new to ASP.NET MVC and the Web API in particular.
panesofglass
Member
730 Points
237 Posts
Re: HttpResponseMessage that plays nice with content negotiation
Mar 28, 2012 06:29 PM|LINK
Your best bet is to take serialization into your own hands. You can see a sample at WebApiContrib.
Kiran Challa
Participant
1442 Points
281 Posts
Microsoft
Re: HttpResponseMessage that plays nice with content negotiation
Mar 28, 2012 08:33 PM|LINK
There is a property called 'Request' which is available for every ApiController derived controller. This property will give you access to the current request from which you should be able to get the information about the headers you want. I am not sure if i answered your question.
Kiran Challa
josheinstein
0 Points
3 Posts
Re: HttpResponseMessage that plays nice with content negotiation
Mar 29, 2012 05:12 AM|LINK
@kiran: That's what I was trying to avoid doing. I wanted to use the built-in content type negotiation and just get access to the decision. If I use the request headers directly, I'll be duplicating the effort and it wouldn't adapt with changes to the conneg strategy.
josheinstein
0 Points
3 Posts
Re: HttpResponseMessage that plays nice with content negotiation
Mar 29, 2012 05:15 AM|LINK
@panesofglass: I'm already doing the serialization myself, but your sample (in addition to the library's source) has pointed me in the right direction. It doesn't look like it's going to be as straightforward as I thought since content negotiation apparently isn't performed at all until a serializable object is returned. Since I'm handling the serialization, looks like I have to do the content type negotiation as well.
imran_ku07
All-Star
45815 Points
7698 Posts
MVP
Re: HttpResponseMessage that plays nice with content negotiation
Apr 01, 2012 05:35 AM|LINK
May be you are looking this,
public class MyFormatterSelector : FormatterSelector { protected override MediaTypeFormatter OnSelectWriteFormatter(Type type, FormatterContext formatterContext, IEnumerable<MediaTypeFormatter> formatters, out MediaTypeHeaderValue mediaType) { var m = base.OnSelectWriteFormatter(type, formatterContext, formatters, out mediaType); return m; } protected override MediaTypeFormatter OnSelectReadFormatter(Type type, FormatterContext formatterContext, IEnumerable<MediaTypeFormatter> formatters) { var m = base.OnSelectReadFormatter(type, formatterContext, formatters); return m; } } GlobalConfiguration.Configuration.ServiceResolver.SetService(typeof(IFormatterSelector), new MyFormatterSelector());Excellent Windows VPS Hosting
Imran Baloch MVP, MVB, MCP, MCTS, MCPD
Mike Stall
Member
5 Points
2 Posts
Microsoft
Re: HttpResponseMessage that plays nice with content negotiation
Apr 20, 2012 10:05 PM|LINK
FWIW, FormatterSelector has been changed and renamed to IContentNegotiator. But you can still get it and explicitly invoke this method:
ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters);
imran_ku07
All-Star
45815 Points
7698 Posts
MVP
Re: HttpResponseMessage that plays nice with content negotiation
Apr 21, 2012 07:59 AM|LINK
Thanks But I think Current Official Build(not talking about current source) does not have IContentNegotiator. BTW, Thanks for letting us.
Excellent Windows VPS Hosting
Imran Baloch MVP, MVB, MCP, MCTS, MCPD
rstrahl
Contributor
2233 Points
375 Posts
ASPInsiders
MVP
Re: HttpResponseMessage that plays nice with content negotiation
Apr 21, 2012 09:06 PM|LINK
Josh,
Is this just for a single request or for all of your requests in the API?
If it's just for a single request it's probably easiest to just case block your output based on the specified option. You can then use the appropriate Request headers to examine the requested accept headers and decide what to do. Alternately (in post beta builds) you can use Request.CreateResponse() to create the Response object with the conneg matched output message type.
I think the latter is probably not going to work well if you are returning non-fixed formats like HTML strings etc., but you can create the response and check if it's XML/JSON and then use that or create a new Response object for the non-internally supported output types like html. If all your requests require this you should probably create a custom output Formatter that handles all the output types you're creating in one place. You then can check the accept headers in there and create the appropriate response. Frankly though if all your requests do this then you're not taking great advantage of what the API offers (other than routing) really and you might be better off just creating a custom Http Handler, which might just be more straight forward.
+++ Rick ---
West Wind Technologies
Making waves on the Web
www.west-wind.com/weblog