请参阅最小 API 概述的显式参数绑定部分:
.NET 6不支持从表单值绑定。
据推测,它们仅指最少的 API,因为在 ASP.NET Core 的模型绑定中没有提到这一点。因此,不幸[FromForm]
的是,.NET 6 不支持使用表单中的属性和绑定,至少在最小的 API 中是这样(我还没有测试过其他场景)。
自定义模型绑定解决方法
有一种使用自定义模型绑定的解决方法。这受到 Ben Foster 的帖子Custom Model Binding in ASP.NET 6.0 Minimal APIs的启发。基本思想是BindAsync
使用以下签名向您的类型/类添加一个方法:
public static ValueTask<TModel?> BindAsync(HttpContext httpContext, ParameterInfo parameter)
对于您的示例,我创建了一个record
具有 3 个属性Id
和. 然后,您使用collection 从以下位置获取所需的值:Name
Status
HttpContext.Request.Form
Request
public record CreateTicketDto(int Id, string Name, string Status)
{
public static ValueTask<CreateTicketDto?> BindAsync(HttpContext httpContext, ParameterInfo parameter)
{
// parse any values required from the Request
int.TryParse(httpContext.Request.Form["Id"], out var id);
// return the CreateTicketDto
return ValueTask.FromResult<CreateTicketDto?>(
new CreateTicketDto(
id,
httpContext.Request.Form["Name"],
httpContext.Request.Form["Status"]
)
);
}
}
现在,您可以使用 FormData 将数据发送到 API 而不会收到错误。
就个人而言,我会[FromForm]
从端点中删除该属性,但是,在我的测试中,无论有没有它,它都可以工作。上述技术也适用于class
类型,而不仅仅是record
s。
更简单的选择
一个更简单的实现是传递HttpContext
给动作并从ctx.Request.Form
集合中读取所有值。在这种情况下,您的操作可能类似于以下内容:
app.MapPost("/tickets", (HttpContext ctx, IFreshdeskApiService s) =>
{
// read value from Form collection
int.TryParse(ctx.Request.Form["Id"], out var id);
var name = ctx.Request.Form["Name"];
var status = ctx.Request.Form["Status"];
var dto = new CreateTicketDto(id, name, status);
s.Add(dto);
return Results.Accepted(value: dto);
});