Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
}
like image 450
Green_qaue Avatar asked Oct 09 '17 12:10

Green_qaue


2 Answers

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

like image 141
Nkosi Avatar answered Oct 04 '22 16:10

Nkosi


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.

like image 25
DiplomacyNotWar Avatar answered Oct 04 '22 16:10

DiplomacyNotWar