我需要处理具有路由参数
的原始请求主体和MVC核心控制器[HttpPut]
[Route("api/foo/{fooId}")]
public async Task Put(string fooId)
{
reader.Read(Request.Body).ToList();
await _store.Add("tm", "test", data);
}
但似乎模型绑定器在到达控制器时已经消耗了请求流。
如果删除路由参数,我可以访问请求流(因为框架将不再处理流以查找参数)。 如何指定两个路由参数并能够访问Request Body而无需手动解析请求URI等。
我尝试用[FromRoute]装饰我的参数,但它没有效果。
如何让框架从Uri,QueryString等绑定参数,但将请求体留给我?
答案 0 :(得分:1)
我怀疑根本原因是MVC检查请求体以尝试绑定路由参数。根据{{3}},这是默认情况下模型绑定对非参数的任何路由的工作方式。
但是,只有在未指定请求内容类型或表单数据(我假设为multipart或url-encoded)时,框架才会执行此操作。
将我的请求内容类型更改为除表单数据之外的任何内容(例如application / json)我可以让框架忽略正文,除非特别需要(例如使用[FromBody]路由参数)。对于我的案例,这是一个可接受的解决方案,因为我只对使用内容类型application / json接受JSON有效负载感兴趣。
@Tseng指出的documentation中的DisableFormValueModelBindingAttribute的实现似乎是一种更好的方法,所以我会考虑使用它来代替完整的
答案 1 :(得分:0)
在代码中定义此属性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
现在用它装饰你的动作方法:
[HttpPut]
[Route("api/foo/{fooId}")]
[DisableFormValueModelBinding]
public async Task Put(string fooId)
{
reader.Read(Request.Body).ToList();
await _store.Add("tm", "test", data);
}
该属性的工作原理是删除将尝试读取请求主体的Value Providers,只留下从路由或查询字符串提供值的那些。
HT @Tseng用于定义此属性的链接Uploading large files with streaming