发布对象数组时从 Web API 接收 405 HTTP 响应 (.Net Core 5)

Receiving a 405 HTTP Response from Web API when posting an array of objects (.Net Core 5)

我在 Orange Pi 的 Linux (Debian 10) 上有一个 .Net Core 5 控制台应用程序 运行。 我正在尝试 post 一些 JSON 到 Web API(也是用 .Net Core 5 编写并托管在 Azure App Service 上) API 有两个 HTTPPOST 端点 - 一个用于接收单个对象,另一个几乎相同的端点用于接收所述对象的数组。

当我 post 将单个对象发送到第一个端点时,我收到 201 Created 状态代码响应。但是当我 post 一个相同对象的数组时, API returns 一个 405 响应:

StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: {
Server: Microsoft-IIS/10.0 Request-Context: appId= X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;Secure;Domain=eball-api.azurewebsites.net Set-Cookie: ARRAffinitySameSite=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;SameSite=None;Secure;Domain=eball-api.azurewebsites.net Date: Sun, 28 Feb 2021 18:58:41 GMT Content-Length: 175
Content-Type: application/problem+json; charset=utf-8 }

这是我的控制台应用程序的样子:

public partial class ReadingDto
{
    public int? Id { get; set; }
    public DateTime? TimeReceived { get; set; }
    public double? Frequency { get; set; }
    public byte? FrequencyByte { get; set; }
    public byte? Modulation { get; set; }
    public byte? AGC1 { get; set; }
    public byte? AGC2 { get; set; }
    public string RawData { get; set; }
    public bool? IsTest { get; set; }
    public bool IsReported { get; set; }
    public DateTime? TimeReported { get; set; }
}

private async Task PostReadings(List<ReadingDto> readingsDto)
{
    using (var httpClient = new HttpClient())
    {
        httpClient.BaseAddress = "https://somedomain.com/api/";
        string serializedObject = JsonSerializer.Serialize(readingsDto);
        StringContent content = new StringContent(serializedObject);
        using (var response = await httpClient.PostAsync("readings/batch", content))
        {
            Console.Write(response.IsSuccessStatusCode);
        }
    }
}

这就是 API 控制器中的操作方法:

[Route("api/[controller]")]
[ApiController]
public class ReadingsController : Controller
{
    [HttpPost("batch")]
    public async Task<IActionResult> PostReadings([FromBody] List<ReadingDto> readingsDto)
    {
        List<Reading> readings = _mapper.Map<List<Reading>>(readingsDto);
        _context.Readings.AddRange(readings);
        await _context.SaveChangesAsync();
        return Created("GetReadings", readings);
    }
}

有什么想法吗?我搜索了很多论坛,大多数建议替换这一行:

StringContent content = new StringContent(serializedObject);

有了这个

StringContent content = new StringContent(serializedObject, Encoding.UTF8, "application/json");

但是当我这样做时,我得到了这个错误:

StatusCode: 400, ReasonPhrase: 'Bad Request', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: {
Transfer-Encoding: chunked Server: Microsoft-IIS/10.0
Request-Context: appId= X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;Secure;Domain=eball-api.azurewebsites.net Set-Cookie: ARRAffinitySameSite=10f4677b6e2472959a213314a4f212e32905ecb3d38e1a47aefbb00645a0d541;Path=/;HttpOnly;SameSite=None;Secure;Domain=eball-api.azurewebsites.net Date: Sun, 28 Feb 2021 19:07:45 GMT Content-Type: application/problem+json; charset=utf-8 }

我会通过使用 System.Net.Http.Formatting 包中包含的 PostAsJsonAsync 来完全避免 StringContent

await httpClient.PostAsJsonAsync("url", readingsDto);

此外,我建议使用 IHttpClientFactory 创建 HttpClient

我设法找出问题所在。客户端使用的 ReadingDto class 与 API 使用的 ReadingDto class 略有不同。客户端版本的数据类型是可为空的整数,而 API 版本是不可为空的整数。所以客户端试图 POST Id 字段中的空值,API 不喜欢。

对于浪费大家的时间,我深表歉意。不幸的是,我不能在上班时间处理这个项目,因为我当时在工作,所以我必须在下班后处理(然后只有在我儿子睡着后(晚上 10 点左右))!这就是工作到很晚很累的问题!