构建ASP.Net Core(V2)MVC站点。
我们正在使用API版本。
该网站有控制器提供MVC Razor Views以及API风格的Json响应。
我正在尝试使用UseExceptionHandler()方法,如下所示。
当我在其中一个操作中遇到异常时,操作会再次执行,然后显示空白页面。浏览器控制台也没有任何错误。最后,我的错误动作永远不会被击中。
我为API控制器安装了一个自定义异常过滤器,如下所示。我已经对此进行了评论,认为这是干扰。这并没有解决任何问题。
我哪里错了?如果出现异常,我如何才能点击自定义错误页面。
异常处理程序方法 - 这导致" /v1.0/home/error"
app.UseExceptionHandler($"/v{appSettings.Value.APIVersion}/home/error");
在阅读之后我也尝试过这应该是视图的路径
app.UseExceptionHandler("/error");
和
app.UseExceptionHandler("/views/home/error");
错误操作
[HttpGet("error")]
public IActionResult Error()
{
var exception = HttpContext.Features.Get<IExceptionHandlerFeature>();
ViewData["statusCode"] = HttpContext.Response.StatusCode;
ViewData["message"] = exception.Error.Message;
return View();
}
异常过滤器(当前在startup.cs中注释掉)
public override void OnException(ExceptionContext context)
{
if (context.HttpContext.Request.Path.Value.Contains("/api"))
{
// Set the response
context.ModelState.GroupErrorsIntoKey("ErrorArray");
context.ModelState.AddModelError("ErrorArray", context.Exception.Message);
context.Result = new BadRequestObjectResult(context.ModelState);
}
}
答案 0 :(得分:3)
我有一个类似的Razor / API混合设计,遇到了同样的问题。显然,这是由于2.0中的动作解析过程发生了更改而发生的。本期“ Problems using UseExceptionHandler()”对此进行了详细介绍,并提供了解决方法。
引用Microsoft / aspnet-api-versioning开发人员提供的解释(从上面的链接):
”之所以会发生此问题,是因为2.0中的动作解析过程发生了变化,该变化修复了一个错误,该错误影响了1.0中的部分(但不是全部)错误。第一个动作匹配。如果没有任何动作,则采用错误路径,通常为404。这是由于平台可能多次调用动作选择器而造成的,此行为的结果是API版本控制无法进行它的决定直到所有可能的路由都被考虑到为止。唯一知道的方法是捕获最后执行的所有路由。不幸的是,这会导致路由行为的另一端表现出意外的行为。可以想象,在每个请求上重新评估整个路由树是非常低效的。为了优化,API版本控制会跟踪给定路由的版本控制策略是否至少评估过一次。最终决定要早得多在管线中。这是导致您首先看到事情未达到预期效果,然后再进行后续调用的行为。”
解决方法是对UseExceptionHandler()进行一些不同的配置。这是对我有用的东西:
app.UseExceptionHandler(new ExceptionHandlerOptions
{
ExceptionHandler = async context =>
{
var exception = context.Features.Get<IExceptionHandlerFeature>().Error;
if (!context.Request.Path.StartsWithSegments(new PathString("/api"), StringComparison.OrdinalIgnoreCase))
{
context.Response.Redirect("Error");
}
else
{
context.Response.ContentType = "application/json";
var response = new
{
Error = exception.Message
};
await context.Response.WriteAsync(JsonConvert.SerializeObject(response));
}
}
});