我有一个 .NET 8 Web API 控制器,其中包含以下端点方法:
[HttpPost()]
[Route("someRoute")]
[ProducesResponseType(typeof(SomeResponse), StatusCodes.Status200OK)]
public async Task<IActionResult> GetSomething([FromForm] SomeComplexRequest request, CancellationToken cancellationToken)
{
//Map request to some MediatR command, send and get result
return Ok(result.Value);
}
它内部实际执行的操作与我的问题无关。在我将 Refit 引入我的项目之前,此端点工作得非常好(我使用的是定制的 HttpClient 实现)。
SomeComplexRequest 类如下所示:
public sealed class SomeComplexRequest
{
[Required]
[FromForm(Name = "SomeID")]
public Guid? SomeID { get; set; }
[Required]
[FromForm(Name = "Offset")]
public int? Offset { get; set; }
[Required]
[FromForm(Name = "Length")]
public int? Length { get; set; }
public SomeComplexRequest(Guid? someID, int? offset, int? length)
{
SomeID = someID;
Offset = offset;
Length = length;
}
public SomeComplexRequest()
{
}
}
我的问题是我的 Refit 方法只有这样写才有效:
[Post("/api/SomeController/someRoute")]
[Multipart]
Task<ApiResponse<IEnumerable<SomeResponse>>> GetSomething(string someID, int offset, int length);
我对SomeID的Guid vs. string情况的理解是Refit实际上并不支持Guid作为参数类型。这并不理想,但实际上并不是一个大问题,因为控制器最终仍然可以理解该参数,无论它是作为 Guid 还是字符串发送的。但我觉得非常烦人的是,Refit 方法似乎需要列出构成我的请求的所有单独参数,而不是只接受 SomeComplexRequest 的实例,无论 Id 是 Guid 还是字符串。它似乎无法将请求分解为单独的参数。这个签名不起作用:
[Post("/api/SomeController/someRoute")]
[Multipart]
Task<ApiResponse<IEnumerable<SomeResponse>>> GetSomething(SomeComplexRequest request);
我有大量的非 Multipart 端点(在 api 控制器方法中用 FromBody 注释),并且这些端点可以与类似的复杂请求对象一起正常工作(其中也有 Guid,请注意)。这是其中之一:
[Post("/api/SomeOtherController")]
Task<ApiResponse<SomeOtherResponse>> AddSomeComplexThing(SomeEvenMoreComplexRequest);
为了简洁起见,我不会展示该要求,但它有 8 个参数,包括字符串、Guids 和 Enums。该方法在端点方法的参数中有 FromBody 并且工作正常。
Multipart 方法是否不支持像普通 JSON 主体方法那样支持复杂对象作为输入参数?
我的问题部分是由于误解了多部分请求的含义。顾名思义,它是一个由多个请求组成的请求,通常用于上传文件和一些元数据。
我的 FromForm REST API 端点的第一个实现就是为了做到这一点,所以我错误地将 FromForm 与 Multipart 关联起来,认为它们必须结合在一起。我这里有问题的请求实际上只是表单中的分页请求,因此不需要 Multipart 开始。多部分方面似乎是阻止复杂对象用作客户端参数的原因。一旦我删除它并在所述请求对象前面指定
[Body(BodySerializationMethod.UrlEncoded)]
,它就开始工作。