我希望能够在操作中读取请求正文,同时仍然使用默认的 MVC 行为,其中涉及使用 [FromBody] 参数进行发布。据我所知,我需要中间件来完成此任务。我的行动是:
[HttpPost]
public async Task<JsonResult> ValidateTestFormAsync([FromBody] ValidationRequest<PersonModel> personValidationRequest)
{
Request.EnableBuffering();
Request.Body.Seek(0, SeekOrigin.Begin);
string requestContent;
using (var reader = new StreamReader(Request.Body, Encoding.UTF8, true, 1024, true))
{
requestContent = await reader.ReadToEndAsync();
}
return Json(requestContent);
}
这不起作用,requestContent 始终为 null,因为一旦请求已经在操作内,请求正文流已被读取并且无法再次读取。如果我删除 [FromBody],它就会起作用。我知道我可以在program.cs中编写一个中间件,如下所示:
app.Use((context, next) =>
{
context.Request.EnableBuffering();
return next();
});
但是这样做有什么考虑呢?我不希望每个请求都是可缓冲的,并且我仍然想通过 [FromBody] 传递模型以坚持 MVC 标准。
我基本上只是尝试运行自定义验证,在其中删除未在帖子中发送的字段/属性的任何错误消息,因为 MVC 始终验证完整模型,并且我尝试逐个字段进行 POST。我以为我可以通过请求正文将
ModelState
错误与发布的值键进行比较,但这似乎不符合我的要求。
如果不需要
ValidationRequest<PersonModel>
对象,则可以完全删除该参数,然后主体将可读,因为 ASP.NET Core 不会读取它。
如果您确实需要,但希望有选择地启用缓冲,则可以使用带有
IAsyncResourceFilter
: 的自定义属性
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class EnableBufferingAttribute : Attribute, IAsyncResourceFilter
{
private readonly Action<HttpRequest> _apply;
public EnableBufferingAttribute()
{
_apply = r => r.EnableBuffering();
}
public EnableBufferingAttribute(int bufferThreshold)
{
_apply = r => r.EnableBuffering(bufferThreshold: bufferThreshold);
}
public EnableBufferingAttribute(int bufferThreshold, long bufferLimit)
{
_apply = r => r.EnableBuffering(bufferThreshold: bufferThreshold, bufferLimit: bufferLimit);
}
public EnableBufferingAttribute(long bufferLimit)
{
_apply = r => r.EnableBuffering(bufferLimit: bufferLimit);
}
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
{
_apply(context.HttpContext.Request);
await next();
}
}
用途:
[EnableBuffering]
[HttpPost]
public async Task<JsonResult> ValidateTestFormAsync([FromBody] ValidationRequest<PersonModel> personValidationRequest)
{
}