ASP.Net Core MVC UseExceptionHandler导致空白页面

时间:2018-03-06 15:51:34

标签: c# asp.net-core asp.net-core-mvc

构建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);
         }
 }

1 个答案:

答案 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));
     }
   }
});