meekree
meekree

Reputation: 61

C# HttpClient returns 415 Unsupported media type on Patch request

We have a .netcore 3.1 ApiController with an endpoint listening for PATCH requests, and defined a Test Server that we're using for the Integration/API tests.

PATCH request sent with Postman works just fine, but requests sent via HttpClient inside the XUnit tests are failing with 415 Unsupported media type.

Postman Patch request: No specific headers other than Bearer token and Content-Type: "application/json"

In the tests, we use WebApplicationFactory and it's factory.CreateClient() for our HttpClient.

It shouldn't be an issue with Json Serialization since I looked into the content through debugger and it seems to be serialized just fine.

Also, our POST methods work completely out of the box with this exact same code (replacing "PATCH" with "POST" etc)

Looking forward to some advices. Also if you need any more info, please let me know. Thanks a lot.

Controller:

[HttpPatch("{id}")]
public async Task<ActionResult<Unit>> Edit(Edit.Command request)
{
     return await Mediator.Send(request);
}

Command:

public class Command : IRequest
{
      public string Id { get; set; }

      public JsonPatchDocument<ObjectDTO> PatchDocument { get; set; }
}

Test:

[InlineData(/* inline data goes here */)]
public async void TestEdit_Ok(/* required parameters for the test */)
{
    var request = new HttpRequestMessage(new HttpMethod("PATCH"), url));
    request.Headers.Add("Authorization", "Bearer " + token);

    /* create patch document logic goes here */

    var command = new Command()
    {
          Id = target,
          PatchDocument = patchDocument,
    };

    _testHelper.AddJsonContent(request, command);

    // Act
    var response = await _client.SendAsync(request);

    // Assert
    Assert.Equal(HttpStatusCode.OK, response.StatusCode);
}

Where helper method AddJsonContent is defined as:

public void AddJsonContent(HttpRequestMessage request, object content)
{
      request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
      string serializedContent = JsonConvert.SerializeObject(content);
      request.Content = new StringContent(serializedContent, Encoding.UTF8, "application/json");
}

Upvotes: 5

Views: 1964

Answers (3)

Abdelrahman Hazem
Abdelrahman Hazem

Reputation: 31

this works for me

var patchResponse = await _client.PatchAsync(endpoint, new StringContent(serializedItemToUpdate,
                    Encoding.Unicode, "application/json-patch+json"));

in constructor, i use basic auth but i u can use other.

        {
            _factory = factory;
            _client = _factory.GetAnonymousClient();
            var authToken = Encoding.ASCII.GetBytes($"user:pass");
            _client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(authToken));
        }

GetAnonymousClient()

using Microsoft.AspNetCore.Mvc.Testing;

 public HttpClient GetAnonymousClient()
        {
            return CreateClient();
        }

Upvotes: 2

meekree
meekree

Reputation: 61

just wanted to say that, while I see this is a confirmed bug, I think once we used full url http://localhost:PORT/endpoint in the client instead of just /endpoint, we didn't encounter this issue anymore. This is the same as one of the proposed workarounds on github issue.

I see the ticket Vadim linked is still open so this may fix the issue for some of you.

Thanks for the help.

Upvotes: 1

Vadim Loboda
Vadim Loboda

Reputation: 3111

The problem is confirmed in Asp.Net Core 5.0 (the problem confirmed by me — I have the same problem as the topic starter)

The PATCH method returns the "415 Unsupported Media Type" status, when using the xUnit with WebApplicationFactory and factory.CreateClient() for HttpClient.

All possible attempts in different combinations results the 415 status.

However, other means like Swagger and Postman work well with the PATCH methods.

Only the xUnit (or WebApplicationFactory) PATCH method fails.

Finally, to conduct the testing, we made a workaround with POST methods, which contain /with-partial-update as a route part.

This bug is reported to aspnetcore repository

Upvotes: -1

Related Questions