【问题标题】:HttpClient.PutAsync - "Entity only allows writes with a JSON Content-Type header"HttpClient.PutAsync - “实体只允许使用 JSON Content-Type 标头写入”
【发布时间】:2017-10-09 12:26:37
【问题描述】:

我有一个可以完美发布数据的 POST 方法。

查看文档,PATCH(或 PUT)看起来应该完全相同,只需使用 PutAsync 而不是 PostAsync

做得好,我得到以下错误:

+       postResponse    {StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.NoWriteNoSeekStreamContent, Headers:
{
  Cache-Control: private
  Date: Mon, 09 Oct 2017 12:19:28 GMT
  Transfer-Encoding: chunked
  request-id: 60370069-f7c4-421d-842e-b1ee8573c2c2
  client-request-id: 60370069-f7c4-421d-842e-b1ee8573c2c2
  x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"North Europe","Slice":"SliceB","ScaleUnit":"002","Host":"AGSFE_IN_7","ADSiteName":"DUB"}}
  Duration: 3.2626
  Content-Type: application/json
}}  System.Net.Http.HttpResponseMessage

然后回应:

实体仅允许使用 JSON Content-Type 标头进行写入

果然在错误中我也可以看到:

ContentType {text/plain; charset=utf-8} System.Net.Http.Headers.MediaTypeHeaderValue

所以这个错误是有道理的,但是,我确实告诉它使用 JSON,并且它在我的 POST 方法中使用相同的代码按预期工作:

public async Task UpdateToGraph(object UnSerializedContent, string relativeUrl)
{
    string accessToken = await _tokenManager.GetAccessTokenAsync();
    HttpContent content = new StringContent(JsonConvert.SerializeObject(UnSerializedContent));

    Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    Client.DefaultRequestHeaders.Add("ContentType", "application/json");

    string endpoint = "https://graph.microsoft.com/v1.0" + relativeUrl;
    var postResponse = Client.PutAsync(endpoint, content).Result;

    string serverResponse = postResponse.Content.ReadAsStringAsync().Result;
}

【问题讨论】:

    标签: c# asp.net-mvc http-headers dotnet-httpclient


    【解决方案1】:

    您可以使用.{Verb}AsJsonAsync HttpClientExtensions 方法。

    public async Task UpdateToGraph(object UnSerializedContent, string relativeUrl) {
        var accessToken = await _tokenManager.GetAccessTokenAsync();
    
        Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        Client.DefaultRequestHeaders.Add("ContentType", "application/json");
    
        var endpoint = "https://graph.microsoft.com/v1.0" + relativeUrl;
        var postResponse = await Client.PutAsJsonAsync(endpoint, UnSerializedContent);
    
        var serverResponse = await postResponse.Content.ReadAsStringAsync();
    }
    

    还要注意 async/await 的正确使用,不要将 .Result 之类的阻塞调用与 async 方法混合使用,因为这会导致死锁。

    参考Async/Await - Best Practices in Asynchronous Programming

    【讨论】:

    • 谢谢,HttpClient does not contain a definition for PutAsJsonAsync,觉得我遗漏了什么? :)
    • @Green_qaue 您可能缺少参考msdn.microsoft.com/en-us/library/…
    • 找到了,谢谢 :) 另一个问题是,如果我删除 .Result,我将无法再访问 postResponse.Content
    • @Green_qaue 你必须await异步调用。如提供的答案所示。
    【解决方案2】:

    使用 StringContent 构造函数设置内容类型:

    HttpContent content = new StringContent(JsonConvert.SerializeObject(UnSerializedContent), System.Text.Encoding.UTF8, "application/json");
    

    据我所知,您并不打算在使用 HttpClient 时在请求对象上设置内容标头。

    【讨论】:

      猜你喜欢
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 2013-07-05
      • 2012-09-06
      • 2014-12-02
      • 2013-07-22
      • 2019-06-28
      相关资源
      最近更新 更多