URIs in media type parameters

Topics: ASP.NET Web API
Mar 31, 2013 at 6:40 PM
Is there a reason why URIs are considered invalid when used as media type parameters?

We can set an Accept header of this form, as long as we bypass validation:
var msg = new HttpRequestMessage();
msg.Headers.TryAddWithoutValidation(
    "Accept",
    "application/hal+json; profile=http://example.org/profile/1");
However, when treated as a collection such a header appears to be empty. I suspect this is related to the validation code around the NameValueHeaderValue class, as attempting to use this to subsequently add the parameter values also fails.

The following code throws a FormatException:
msg.Headers.Accept.ParseAdd(
    "application/hal+json; profile=http://example.org/profile/1");
A little more background on what I'm trying to do, in case that's any help: I'm hoping to use content negotiation to select a media type from the Accept header and then parse its parameters to determine how to format the output.

At the moment I'm struggling to see how to achieve this.
Apr 1, 2013 at 2:44 PM
Edited Apr 1, 2013 at 7:17 PM
Answering my own question: according to the HTTP specification, any media type parameter that contains control characters or separators (space, tab, ( ) < > @ , ; : \ " / [ ] ? = { }) must be enclosed in quotation marks.

I'm still curious if there's a neat way, having run content negotiation on a string such as:

Accept: application/hal+json; profile={uri},application/json; q=0.1

to extract the media type parameters of the matched range. If the formatter is set up in a naive fashion using SupportedMediaTypes, we get the benefits of q-value sorting etc. courtesy of the DefaultContentNegotiator, but any parameter values supplied by the client are lost.

If we write a custom RequestHeaderMapping, we're forced to reimplement a lot of this logic ourselves, and I'm still unsure of the best way to pass the parameters to the formatter for use in the SetDefaultContentHeaders method.

Does anybody have any pointers on the best way to accomplish this?