Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何设置HttpClient请求的内容类型标头?_C#_Asp.net_Rest_Content Type_Dotnet Httpclient - Fatal编程技术网

C# 如何设置HttpClient请求的内容类型标头?

C# 如何设置HttpClient请求的内容类型标头?,c#,asp.net,rest,content-type,dotnet-httpclient,C#,Asp.net,Rest,Content Type,Dotnet Httpclient,我正在尝试设置HttpClient对象的Content-Type头,以满足我调用的API的要求 我尝试设置内容类型,如下所示: using (var httpClient = new HttpClient()) { httpClient.BaseAddress = new Uri("http://example.com/"); httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); httpC

我正在尝试设置
HttpClient
对象的
Content-Type
头,以满足我调用的API的要求

我尝试设置
内容类型
,如下所示:

using (var httpClient = new HttpClient())
{
    httpClient.BaseAddress = new Uri("http://example.com/");
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("Content-Type", "application/json");
    // ...
}
它允许我添加
Accept
标题,但当我尝试添加
内容类型时,它会引发以下异常:

误用的标题名。确保请求头与
HttpRequestMessage
,带有
HttpResponseMessage
的响应头,以及 包含
HttpContent
对象的内容标题


如何在
HttpClient
请求中设置
Content-Type
标题?

调用
AddWithoutValidation
,而不是
Add
(请参阅)


或者,我猜您正在使用的API实际上只对POST或PUT请求(而不是普通的GET请求)要求这样做。在这种情况下,当您调用
HttpClient.PostAsync
并传入
HttpContent
时,在该
HttpContent
对象的
Headers
属性上设置该属性。

内容类型是内容的头,而不是请求的头,这就是失败的原因。可以工作,但您也可以在创建请求内容本身时设置内容类型(请注意,代码段在两个位置添加了
application/json
,用于Accept和content-type头):


对于那些没有看到约翰评论卡洛斯解决方案的人

req.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

如果你不介意一个小的库依赖,[披露:我是作者]使优步变得简单。它的
PostJsonAsync
方法负责序列化内容和设置
content-type
标题,并且
ReceiveJson
反序列化响应。如果需要
accept
标题,您需要自己设置,但Flurl也提供了一种非常简洁的方法:

using Flurl.Http;

var result = await "http://example.com/"
    .WithHeader("Accept", "application/json")
    .PostJsonAsync(new { ... })
    .ReceiveJson<TResult>();

尝试在没有验证的情况下使用tryadd

  var client = new HttpClient();
  client.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");

.Net试图强制您遵守某些标准,即
内容类型
标题只能在包含内容的请求上指定(例如
POST
PUT
等)。因此,正如其他人所指出的,设置
内容类型
标题的首选方法是通过属性

尽管如此,某些API(如,截至2016年12月19日)需要为
GET
请求设置
内容类型
标题。Net将不允许在请求本身上设置此标头--即使使用
tryadd而不进行验证
。此外,您不能为请求指定
内容
——即使它的长度为零。我似乎唯一能绕过这个问题的方法就是诉诸反思。代码(以防其他人需要)是

var field=typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField(“invalidHeaders”,System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
?? typeof(System.Net.Http.Headers.HttpRequestHeaders)
.GetField(“s_invalidHeaders”,System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
如果(字段!=null)
{
var invalidFields=(HashSet)field.GetValue(null);
invalidFields.Remove(“内容类型”);
}
_client.DefaultRequestHeaders.TryAddWithoutValidation(“内容类型”、“文本/xml”);
编辑:


如注释中所述,此字段在dll的不同版本中具有不同的名称。在中,该字段当前命名为
s\u invalidHeaders
。根据@David Thompson的建议,对示例进行了修改以说明这一点。

关于.NET Core的一些额外信息(在阅读了erdomke关于设置私有字段以在没有内容的请求上提供内容类型的帖子之后)

调试完代码后,我看不到要通过反射设置的私有字段,所以我想我应该尝试重新创建这个问题

我使用.Net 4.6尝试了以下代码:

HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Get, @"myUrl");
httpRequest.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpClient client = new HttpClient();
Task<HttpResponseMessage> response =  client.SendAsync(httpRequest);  //I know I should have used async/await here!
var result = response.Result;
HttpRequestMessage httpRequest=newhttprequestmessage(HttpMethod.Get,@“myUrl”);
httpRequest.Content=newstringcontent(string.Empty,Encoding.UTF8,“application/json”);
HttpClient=新的HttpClient();
任务响应=client.sendaync(httpRequest)//我知道我应该在这里使用async/Wait!
var result=response.result;
而且,正如预期的那样,我得到了一个聚合异常,内容为“无法发送具有此动词类型的内容正文。”

但是,如果我对.NET Core(1.1)做同样的事情,我不会得到例外。我的服务器应用程序很高兴地回答了我的请求,并且选择了内容类型

我对此感到惊喜,我希望这对别人有帮助

var content = new JsonContent();
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", "utf-8"));
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("IEEE754Compatible", "true"));
这就是你所需要的

使用Newtonsoft.Json,如果您需要一个内容作为Json字符串

public class JsonContent : HttpContent
   {
    private readonly MemoryStream _stream = new MemoryStream();
    ~JsonContent()
    {
        _stream.Dispose();
    }

    public JsonContent(object value)
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var contexStream = new MemoryStream())
        using (var jw = new JsonTextWriter(new StreamWriter(contexStream)) { Formatting = Formatting.Indented })
        {
            var serializer = new JsonSerializer();
            serializer.Serialize(jw, value);
            jw.Flush();
            contexStream.Position = 0;
            contexStream.WriteTo(_stream);
        }
        _stream.Position = 0;

    }

    private JsonContent(string content)
    {
        Headers.ContentType = new MediaTypeHeaderValue("application/json");
        using (var contexStream = new MemoryStream())
        using (var sw = new StreamWriter(contexStream))
        {
            sw.Write(content);
            sw.Flush();
            contexStream.Position = 0;
            contexStream.WriteTo(_stream);
        }
        _stream.Position = 0;
    }

    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        return _stream.CopyToAsync(stream);
    }

    protected override bool TryComputeLength(out long length)
    {
        length = _stream.Length;
        return true;
    }

    public static HttpContent FromFile(string filepath)
    {
        var content = File.ReadAllText(filepath);
        return new JsonContent(content);
    }
    public string ToJsonString()
    {
        return Encoding.ASCII.GetString(_stream.GetBuffer(), 0, _stream.GetBuffer().Length).Trim();
    }
}

好的,它不是HTTPClient,但如果您可以使用它,WebClient非常简单:

using (var client = new System.Net.WebClient())
 {
    client.Headers.Add("Accept", "application/json");
    client.Headers.Add("Content-Type", "application/json; charset=utf-8");
    client.DownloadString(...);
 }

我发现以下方式最简单、最容易理解:

异步任务SendPostRequest()
{
HttpClient=新的HttpClient();
var requestContent=new StringContent();
requestContent.Headers.ContentType=新的MediaTypeHeaderValue(“应用程序/json”);
var response=wait client.PostAsync(,requestContent);
var responseString=await response.Content.ReadAsStringAsync();
}
...
SendPostRequest().Wait();

你可以用这个,它会有用的

HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get,"URL");
msg.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpResponseMessage response = await _httpClient.SendAsync(msg);
response.EnsureSuccessStatusCode();

string json = await response.Content.ReadAsStringAsync();

您需要这样做:

    HttpContent httpContent = new StringContent(@"{ the json string }");
    httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                
    HttpResponseMessage message = client.PostAsync(@"{url}", httpContent).Result;
对于那些遇到
charset
我遇到了一个非常特殊的情况,服务提供商不接受charset,他们拒绝更改子结构以允许它。。。 不幸的是,HttpClient是通过StringContent自动设置标题的,无论您传递null还是Encoding.UTF8,它都会设置字符集

今天我在改变子系统的边缘;从HttpClient转移到其他任何东西,这是某种东西产生的结果
using (var client = new System.Net.WebClient())
 {
    client.Headers.Add("Accept", "application/json");
    client.Headers.Add("Content-Type", "application/json; charset=utf-8");
    client.DownloadString(...);
 }
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get,"URL");
msg.Content = new StringContent(string.Empty, Encoding.UTF8, "application/json");

HttpResponseMessage response = await _httpClient.SendAsync(msg);
response.EnsureSuccessStatusCode();

string json = await response.Content.ReadAsStringAsync();
    HttpContent httpContent = new StringContent(@"{ the json string }");
    httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));                
    HttpResponseMessage message = client.PostAsync(@"{url}", httpContent).Result;
var jsonRequest = JsonSerializeObject(req, options); // Custom function that parse object to string
var stringContent = new StringContent(jsonRequest, Encoding.UTF8, "application/json");
stringContent.Headers.ContentType.CharSet = null;
return stringContent;
return new StringContent(jsonRequest, null, "application/json");
stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
services.AddSingleton<WebRequestXXX>()
        .AddHttpClient<WebRequestXXX>("ClientX", config =>
        {
           config.BaseAddress = new System.Uri("https://jsonplaceholder.typicode.com");
           config.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
           config.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json; charset=utf-8");
        });
public class WebRequestXXXX
{
    private readonly IHttpClientFactory _httpClientFactory;

    public WebRequestXXXX(IHttpClientFactory httpClientFactory)
    {
        _httpClientFactory = httpClientFactory;
    }

    public List<Posts> GetAllPosts()
    {
        using (var _client = _httpClientFactory.CreateClient("ClientX"))
        {
            var response = _client.GetAsync("/posts").Result;

            if (response.IsSuccessStatusCode)
            {
                var itemString = response.Content.ReadAsStringAsync().Result;
                var itemJson = System.Text.Json.JsonSerializer.Deserialize<List<Posts>>(itemString, 
                    new System.Text.Json.JsonSerializerOptions 
                    {
                        PropertyNameCaseInsensitive = true
                    });

                return itemJson;
            }
            else
            {
                return new List<Posts>();
            }
        }
    }
}
private void FixContentTypeHeaders()
{
    var assembly = typeof(System.Net.Http.Headers.HttpRequestHeaders).Assembly;
    var assemblyTypes = assembly.GetTypes();

    var knownHeaderType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeader");
    var headerTypeField = knownHeaderType?
                .GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
                .FirstOrDefault(n => n.Name.Contains("HeaderType"));
    if (headerTypeField is null) return;

    var headerTypeFieldType = headerTypeField.FieldType;            
    var newValue = Enum.Parse(headerTypeFieldType, "All");

    var knownHeadersType = assemblyTypes.FirstOrDefault(n => n.Name == "KnownHeaders");
    var contentTypeObj = knownHeadersType.GetFields().FirstOrDefault(n => n.Name == "ContentType").GetValue(null);

    if (contentTypeObj is null) return;

    headerTypeField.SetValue(contentTypeObj, newValue);
}
        private async Task<string> GetAccessTokenAsync()
        {
            var client = new RestClient(_baseURL);

            var request = new RestRequest("auth/v1/login", Method.POST, DataFormat.Json);

            request.AddHeader("Content-Type", "application/json");
            request.AddHeader("x-api-key", _apiKey);
            request.AddHeader("Accept-Language", "br");
            request.AddHeader("x-client-tenant", "1");
        
            ...
        }