问题
Is there a way in which I can explicitly set the Content-Type
header values when performing a GET
with HttpClient
?
I realise this breaks 1.1 protocol, but I am working with a API that does not conform to it, and REQUIRES I set a Content-Type
Header.
I have tried this with to no avail...
using (var httpClient = new HttpClient())
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, "http://example.com");
httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/x-www-form-urlencoded+v1.3");
await httpClient.SendAsync(httpRequestMessage)
}
I've inspected the DefaultRequestHeaders
after the TryAddWithoutValidation
is added, and it does not seem to be setting the Content-Type
value.
If I try to set the Content-Type of the httpRequestMessage (by setting httpRequestMessage.Content = ...
, I get the following error:
Cannot send a content-body with this verb-type.
Is there a way that I can explicitly set the Content-Type
for a GET
operation using the HttpClient?
回答1:
Based on my findings i concluded the HttpClient is very restrictive in terms of the protocol rules. I also reflected through the implementation DLL and i couldn't find anything that it would indicate that it allows protocol violations.
GET requests shouldn't have content-type headers, and the HttpClient is enforcing that rule.
I think the exception message when you try to set the content-type header is self-descriptive:
System.InvalidOperationException: Misused header name. Make sure request headers are used with HttpRequestMessage, response headers with HttpResponseMessage, and content headers with HttpContent objects.
Also if you use set the content body you get one more self-descriptive message:
System.Net.ProtocolViolationException: Cannot send a content-body with this verb-type.
Since you are willing to violate HTTP rules for GET requests i am pretty sure your only option is to stick with the less restrictive WebClient, which works in that scenario.
回答2:
It's possible - and very dirty - to override the library behavior with a bit of reflection and by introducing a DelegatingHandler
that you give as argument to the HttpClient
constructor. See the code below.
public class HmacAuthenticatingHandler : DelegatingHandler
{
public HmacAuthenticatingHandler(HttpMessageHandler innerHandler)
: base(innerHandler)
{
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
// HACK: Set 'Content-Type' even for GET requests
var invalidHeaders = (HashSet<string>)typeof(HttpHeaders)
// use "_invalidHeaders" for System.Net.Http v2.2+
.GetField("invalidHeaders", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(request.Headers);
invalidHeaders.Remove("Content-Type");
request.Headers.Remove("Content-Type");
request.Headers.Add("Content-Type", "application/json");
var response = await base.SendAsync(request, cancellationToken);
return response;
}
}
回答3:
Although of no help to you right now, it does look like a future release of the .NET framework may support this type of protocol violation with the addition of an AddWithoutValidation method:
https://msdn.microsoft.com/en-us/library/hh204926
回答4:
Have you tried adding headers to content header (as apposed as a request header) see here
来源:https://stackoverflow.com/questions/26109650/explicitly-set-content-type-headers-for-get-operation-in-httpclient