简体   繁体   中英

HttpClient.PutAsync - “Entity only allows writes with a JSON Content-Type header”

I have a POST method that can post data perfectly.

Looking at docs it seems a PATCH (or PUT) should look the exact same, just use PutAsync instead of PostAsync .

Well doing just that I get the following error:

+       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

And response:

Entity only allows writes with a JSON Content-Type header

And sure enough in the Error I can also see this:

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

So the error makes sense, however, I do tell it to use JSON, and it work as intended in my POST-method with the same code:

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;
}

You can use the .{Verb}AsJsonAsync HttpClientExtensions methods.

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();
}

Also note the proper use of async/await by not mixing blocking calls like .Result with async methods as this can lead to deadlocks.

Reference Async/Await - Best Practices in Asynchronous Programming

Set the content type using the StringContent constructor:

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

As far as I'm aware, you're not meant to set the content header on the request object when using the HttpClient.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM