I am using flurl to submit HTTP request and this is very useful. Now I need to change the "Content-Type" header for some of the requests to "application/json;odata=verbose"
public async Task<Job> AddJob()
{
var flurlClient = GetBaseUrlForGetOperations("Jobs").WithHeader("Content-Type", "application/json;odata=verbose");
return await flurlClient.PostJsonAsync(new
{
//Some parameters here which are not the problem since tested with Postman
}).ReceiveJson<Job>();
}
private IFlurlClient GetBaseUrlForOperations(string resource)
{
var url = _azureApiUrl
.AppendPathSegment("api")
.AppendPathSegment(resource)
.WithOAuthBearerToken(AzureAuthentication.AccessToken)
.WithHeader("x-ms-version", "2.11")
.WithHeader("Accept", "application/json");
return url;
}
You can see how I tried to add the header above (.WithHeader("Content-Type", "application/json;odata=verbose")
)
Unfortunately this gives me following error:
"InvalidOperationException: Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects."
I also tried flurl's "ConfigureHttpClient" method but could not find how/where to set the content type header.
The comments and another post I found (will add reference when I find it again) have pointed me to the right direction. The solution for my problem looks like:
Edit: Found the related SO question: Azure encoding job via REST Fails
Am I allowed to post 3 answers to the same question? :)
Upgrade. Flurl.Http 2.0 includes the following enhancements to headers:
WithHeader(s)
now usesTryAddWithoutValidation
under the hood. With that change alone, the OP's code will work as originally posted.Headers are now set at the request level, which solves another known issue.
When using
SetHeaders
with object notation, underscores in property names will be converted to hyphens in the header names, since hyphens in headers are very common, underscores are not, and hyphens are not allowed in C# identifiers.This will be useful in your case:
This answer is outdated. Upgrade to latest version (2.0 or above) and the problem goes away.
It turns out the real issue has to do with how the
System.Net.Http
APIs validate headers. It makes a distinction between request-level headers and content-level headers, which I've always found a bit odd since raw HTTP makes no such distinction (except perhaps in multipart scenarios). Flurl'sWithHeader
adds headers to theHttpRequestMessage
object but is failing validation forContent-Type
, which it expects to be added to theHttpContent
object.Those APIs do allow you to skip validation, and although Flurl doesn't expose it directly, you can get under the hood pretty easily, without breaking the fluent chain:
This is probably the best way to do what you need and still take advantage of Flurl's goodness, i.e. not have to directly deal with serialization,
HttpContent
objects, etc.I'm strongly considering changing Flurl's
AddHeader(s)
implementations to useTryAddWithoutValidation
based on this issue.I'm not an OData expert and I don't know what API you're calling (SharePoint?), but based on most examples I've seen, what you typically want to do is ask the server to send verbose OData in the response, rather than declare that you're sending it in the request. In other words, you want to set the
;odata=verbose
bit on the Accept header, not Content-Type.application/json
should be good enough for Content-Type, and Flurl will set that for you automatically, so just try this change and see if it works: