I have domain service that throws a custom DomainServiceValidationException
for a business validation. I want to globally capture the exception and return in ModelState. My current working solution is using 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
}
}
}
I want to know if there is any way to access ModelState in UseExceptionHandler middleware
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
}
});
}
}
CodePudding user response:
Shorten answer:
No, you cannot access ModelState in UseExceptionHandler middleware.
Explanation:
Firstly you need to know ModelState is only available after Model Binding.
Then Model Binding invokes before Action Filters
and after Resource Filters
(See Figure 1). But Middleware
invokes before Filters(See Figure 2).
Figure 1:
Figure 2:
Reference:
Conclusion:
That is to say, you can not get the ModelState
in UseExceptionHandler
middleware.
Workaround:
You can only store the ModelState
automatically in Filters(Action Filters or Exception Filters or Result Filters), then you can use it within middleware.
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;
}
});
Reference: