C# HttpClient 在 Patch 请求时返回 415 不支持的媒体类型

5
我们有一个 .netcore 3.1 ApiController,它有一个监听 PATCH 请求的端点,并定义了一个测试服务器用于集成/API 测试。
使用 Postman 发送的 PATCH 请求正常工作,但在 XUnit 测试中使用 HttpClient 发送的请求失败并返回 415 不支持的媒体类型错误。
Postman 的 Patch 请求: 除了 Bearer token 和 Content-Type: "application/json" 之外没有特定的头信息。
在测试中,我们使用 WebApplicationFactory 和它的 factory.CreateClient() 创建 HttpClient。
这不应该是 Json 序列化的问题,因为我通过调试器查看了内容,似乎序列化得很好。
此外,我们的 POST 方法完全可以使用同样的代码(将 "PATCH" 替换为 "POST" 等)。
期待一些建议。如果需要更多信息,请告诉我。非常感谢。
控制器:
[HttpPatch("{id}")]
public async Task<ActionResult<Unit>> Edit(Edit.Command request)
{
     return await Mediator.Send(request);
}

命令:

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

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

测试:

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

辅助方法AddJsonContent的定义如下:

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

你如何配置 WebApplicationFactory?你使用 Startup 吗?它是做什么的?默认情况下,WebApplicationFactory 可能没有配置处理 PATCH - Panagiotis Kanavos
您没有指定服务器接受的Content-Type。使用Post和Patch,您应该指定从客户端发送到服务器的请求的媒体类型。您只指定了客户端期望从响应中获得的accept。我认为默认情况下,Postman正在发送application/json。但请尝试以编程方式以相同的方式添加Accept和Content-Type,并告诉我。 - Zinov
3个回答

2
这对我来说很有效。
var patchResponse = await _client.PatchAsync(endpoint, new StringContent(serializedItemToUpdate,
                    Encoding.Unicode, "application/json-patch+json"));

在构造函数中,我使用了基本身份验证,但你也可以使用其他方式。
        {
            _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));
        }

获取匿名客户端()
using Microsoft.AspNetCore.Mvc.Testing;

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


1

只是想说,虽然我看到这是一个已确认的错误,但是一旦我们在客户端中使用完整的URL http://localhost:PORT/endpoint 而不仅仅是 /endpoint,我们就不再遇到这个问题了。这与GitHub问题上提出的其中一种解决方法相同。

我看到Vadim链接的票仍然是开放状态,所以这可能会为你们中的一些人解决问题。

感谢您的帮助。


-1

问题已在Asp.Net Core 5.0中确认(我已经确认了这个问题——我和主题发起人有相同的问题)

使用xUnit和factory.CreateClient() for HttpClient时,PATCH方法返回“415 Unsupported Media Type”状态。

所有可能的尝试以不同的组合都会导致415状态。

然而,其他工具如Swagger和Postman与PATCH方法配合良好。

只有xUnit(或WebApplicationFactory)的PATCH方法失败。

最后,为了进行测试,我们使用包含/with-partial-update作为路由部分的POST方法进行了解决。

此错误已报告给aspnetcore存储库


1
确认在哪里?有Github问题链接吗?XUnit对HTTP一无所知。“WebApplicationFactory”并不是XUnit的一部分,它是一个ASP.NET Core类,用于集成测试以模拟Web服务器。 Swagger和Postman与此无关,它们是调用真实服务器的客户端。 - Panagiotis Kanavos
如果更改客户端会导致ASP.NET出现问题,那么这不是xUnit的问题吗?您没有链接到任何可靠的来源。 - Tanveer Badar
@WebApplicationFactory是ASP.NET Core的一个类,用于模拟Web服务器进行集成测试。可能存在错误,或者可能只是配置不正确。 - Panagiotis Kanavos
@Panagiotis Kanavos,我确认了这个问题——我和话题发起人遇到了同样的问题。我还将“using the xUnit WebApplicationFactory”更改为“using the xUnit with WebApplicationFactory”。请问可以建议在哪里报告这个问题吗? - Vadim Loboda
@Panagiotis Kanavos,好的,已经报告了:https://github.com/dotnet/aspnetcore/issues/35770 - Vadim Loboda
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接