我几乎总是想检查在回发时是否调用了ModelSate.IsValid
。并且必须在每个帖子的开头检查都违反DRY原则,有没有办法让它自动检查?
示例:
[HttpPost("RegisterUser")]
[AllowAnonymous]
public async Task<IActionResult> RegisterUser([FromBody] UserRegisterViewModel vmodel)
{
if(!ModelState.IsValid) // This code is repeated at every postback
return ModelInvalidAction(); // Is there a way to avoid having to write it down?
// do other things
return StatusCode(201);
}
答案 0 :(得分:3)
框架提供了一个可以子类化的抽象ActionFilterAttribute
。
您可以使用操作过滤器自动验证模型状态,并在状态无效时返回任何错误:
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (!context.ModelState.IsValid)
{
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
}
您可以将其用于个别操作或全局注册
答案 1 :(得分:2)
您可以尝试这样的事情:
public class ValidateModelAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.ModelState.IsValid)
{
filterContext.Result = new BadRequestResult();
}
}
}
您可以请求此filterContext.HttpContext.RequestServices.GetService<ILogger>()
之类的任何注册服务。
您可以通过操作过滤您的操作或控制器:
[HttpPost("RegisterUser")]
[AllowAnonymous]
[ValidateModel]
public async Task<IActionResult> RegisterUser([FromBody] UserRegisterViewModel vmodel)
{
...
}
答案 2 :(得分:1)
我研究了这个并找到了我认为最好的答案。即使我实现了其他答案中提到的内容,我仍然需要在每个POST和PUT请求中添加[ValidateModel]
属性来重复自己,这是我想要的东西为了避免,我还想记录模型无效的事情,其他答案并不是真的允许这样做。所以这是我的答案:
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class ValidateViewModelAttribute : Attribute, IFilterFactory
{
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
var logger = serviceProvider.GetService<ILogger>();
return new InternalValidateModel(logger);
}
private class InternalValidateModel : IActionFilter
{
private ILogger _log;
public InternalValidateModel(ILogger log)
{
_log = log;
}
public void OnActionExecuting(ActionExecutingContext context)
{
if (IsInvalidModelState(context))
{
_log.Information("Invalid ModelState: {Model}", context.ModelState.ErrorMessages());
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
public void OnActionExecuted(ActionExecutedContext context)
{
}
private bool IsInvalidModelState(ActionExecutingContext context)
{
var method = context.HttpContext.Request.Method;
return (method == "POST" ||
method == "PUT") &&
!context.ModelState.IsValid;
}
}
public bool IsReusable => true;
}
我不想在每个POST
和PUT
上添加[ValidateViewModel]来重复自己。所以我做了以下几点:
services.AddMvc(config =>
{
config.Filters.Add(new ValidateViewModelAttribute());
});
现在所有POST
和PUT
方法都已经过验证!!