提问人:Stack Undefined 提问时间:10/18/2023 最后编辑:Stack Undefined 更新时间:10/19/2023 访问量:24
Web API 模型绑定器映射 .NET Framework 4.7 中操作方法参数的 null 值
Web API model binder maps null value for action method parameter in .NET Framework 4.7
问:
使用使用 .NET Framework 4.7 并公开几个 Web API 终结点的旧版应用。参数是一种类型。ICollection<Guid>
[HttpPost("customer/process")]
public async Task<IHttpActionResult> ProcessCustomers([FromBody] ICollection<Guid> customerIds, CancellationToken cancellationToken)
{
// customerIds is null if the collection has more than 24 Guids
}
使用 refit 客户端发出 HTTP post 请求。
public interface IRefitApiClient
{
[HttpPost("/api/xyz/customer/process")]
[Headers("content-type: application/json")]
public async Task<int> ProcessCustomers([Body] IEnumerable<Guid> customerIds, CancellationToken token);
}
身体:
[
"46dadad3-f8da-4a0e-a97d-69a21684f720",
"56da249b-70b2-4e74-998f-4101541ca492",
"3afcc23e-e1f8-4b3b-9ca1-acaf038c86c4",
"7c1321b4-4944-47f7-b248-f65c6acb246e"
.
.
.
]
如果集合具有 24 个或更少的 GUID,则终结点将接收所有 GUID。超过 24 个 GUID,终结点仅接收 null 值。
我尝试增加 Web API 服务中的所有请求限制,但无济于事。该服务在 IIS 上运行,但尚未在那里进行任何更改。这些似乎都无济于事。web.config
maxJsonLength="2147483644"
maxRequestLength="2097151"
maxAllowedContentLength="4294967295"
aspnet:MaxJsonDeserializerMembers value="10000000"
这是对改装客户端的限制,还是我必须在IIS上更改某些内容?但是,当在 VS 的 IIS express 上本地运行服务时,我可以使用 postman 成功发布大约 5000 个 guid 的列表。这表明需要在生产环境中的 IIS 服务器中进行一些调整。TIA系列
更新
在通过它们进行改装之前,我序列化了 200 个 Guid 的列表,它没有任何问题。
var foo = new List<Guid>{'guid1', 'guid2', 'guid3'.....};
var bar = JsonSerializer.Serialize(foo);
var res = _refitApiClient.ProcessCustomers(bar, cancellationToken);
public interface IRefitApiClient
{
[HttpPost("/api/xyz/customer/process")]
[Headers("content-type: application/json")]
public async Task<int> ProcessCustomers([Body] string customerIds, CancellationToken token);
}
正如你在上面看到的,我不得不改成。这很骇人听闻。所以问题毕竟出在改装客户端上。即使我在客户端字符串化了 guid 集合,api 端点也可以正确地将其反序列化为 List,而无需手动干预。IEnumerable<Guid>
string
我在将 DateTime 传递给 api 时遇到了类似的改装问题。我必须像在这里一样将其转换为字符串。我一定在某处缺少一些改装配置。令人惊讶的是,这些模型在通过之前需要被绳子固定。在这个问题上浪费了很多时间。
答:
问题出在改装客户端上。默认情况下,它流式传输 POST 内容,因此不会将 content-length 发送到 api。您希望改装客户端缓冲请求并一次性发送所有请求。
在属性中添加如下内容:Buffered: true
Body
public interface IRefitApiClient
{
[HttpPost("/api/xyz/customer/process")]
[Headers("content-type: application/json")]
public async Task<int> ProcessCustomers([Body(Buffered: true)] IEnumerable<Guid> customerIds, CancellationToken token);
}
现在,模型绑定器不会将参数绑定到 null。缓冲应该是默认设置。我在这个问题上浪费了很多时间!
评论