如何在 UseExceptionHandler 中访问 ModelState
Posted
技术标签:
【中文标题】如何在 UseExceptionHandler 中访问 ModelState【英文标题】:How to access ModelState in UseExceptionHandler 【发布时间】:2022-01-23 01:10:02 【问题描述】:我的域服务会抛出自定义 DomainServiceValidationException
以进行业务验证。我想全局捕获异常并在 ModelState 中返回。我目前的工作解决方案是使用ExceptionFilterAttribute
public class ExceptionHandlerAttribute : ExceptionFilterAttribute
private readonly ILogger<ExceptionHandlerAttribute> _logger;
public ExceptionHandlerAttribute(ILogger<ExceptionHandlerAttribute> logger)
_logger = logger;
public override void OnException(ExceptionContext context)
if (context == null || context.ExceptionHandled)
return;
if(context.Exception is DomainServiceValidationException)
context.ModelState.AddModelError("Errors", context.Exception.Message);
context.HttpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest;
context.Result = new BadRequestObjectResult(context.ModelState);
else
handle exception
想知道UseExceptionHandler中间件有没有办法访问ModelState
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime appLifetime)
app.UseExceptionHandler(new ExceptionHandlerOptions()
ExceptionHandler = async (context) =>
var ex = context.Features.Get<IExceptionHandlerFeature>().Error;
// how to access to ModelState here
);
【问题讨论】:
【参考方案1】:缩短答案:
不,您不能在 UseExceptionHandler 中间件中访问 ModelState。
解释:
首先你需要知道ModelState只有在Model Binding之后才可用。
然后模型绑定在Action Filters
之前和Resource Filters
之后调用(参见图 1)。但是Middleware
在过滤器之前调用(参见图 2)。
图一:
图2:
参考:
How Filters work
结论:
也就是说,你无法在UseExceptionHandler
中间件中获取ModelState
。
解决方法:
您只能将ModelState
自动存储在过滤器(操作过滤器或异常过滤器或结果过滤器)中,然后您可以在中间件中使用它。
app.UseExceptionHandler(new ExceptionHandlerOptions()
ExceptionHandler = async (context) =>
var ex = context.Features.Get<IExceptionHandlerFeature>().Error;
// how to access to ModelState here
var data = context.Features.Get<ModelStateFeature>()?.ModelState;
);
参考:
How to store ModelState automatically
【讨论】:
以上是关于如何在 UseExceptionHandler 中访问 ModelState的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ASP.NET Core 中为 gRPC 服务添加全局异常处理 ?