2016-11-15 114 views
7

我有asp.net核心应用程序。当发生异常时(在非开发环境中),配置方法的实现将用户重定向到“错误”页面在asp.net核心处理异常?

但是,只有当控制器内部出现异常时,它才有效。如果异常发生在控制器之外,例如在我的自定义中间件中,则用户不会重定向到错误页面。

如果中间件出现异常,我该如何将用户重定向到“错误”页面。

 public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 

     app.UseApplicationInsightsRequestTelemetry(); 

     if (env.IsDevelopment()) 
     { 
      app.UseDeveloperExceptionPage(); 
      app.UseBrowserLink(); 
     } 
     else 
     { 
      app.UseExceptionHandler("/Home/Error"); 
     } 

     app.UseApplicationInsightsExceptionTelemetry(); 

     app.UseStaticFiles(); 
     app.UseSession(); 
     app.UseMyMiddleware(); 

     app.UseMvc(routes => 
     { 
      routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 
     }); 
    } 

更新1
我上面用下面的两行中缺少在初始后更新的代码。

 app.UseSession(); 
     app.UseMyMiddleware(); 

此外,我发现为什么app.UseExceptionHandler无法重定向到错误页面。
当我的中间件代码出现异常时,app.UseExceptionHandler("\Home\Error")按预期重定向到\Home\Error;但由于这是一个新的请求,我的中间件再次执行并再次抛出异常。
所以要解决这个问题我改变了我的中间件仅if context.Request.Path != "/Home/Error"

我不知道要执行,如果这是解决这个问题,但其工作的正确方法。

public class MyMiddleWare 
{ 
    private readonly RequestDelegate _next; 
    private readonly IDomainService _domainService; 

    public MyMiddleWare(RequestDelegate next, IDomainService domain) 
    { 
     _next = next; 
     _domainService = domain; 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     if (context.Request.Path != "/Home/Error") 
     { 
      if (context.User.Identity.IsAuthenticated && !context.Session.HasKey(SessionKeys.USERINFO)) 
      {   
       // this method may throw exception if domain service is down 
       var userInfo = await _domainService.GetUserInformation(context.User.Name).ConfigureAwait(false);      

       context.Session.SetUserInfo(userInfo); 
      } 
     } 

     await _next(context); 
    } 
} 

public static class MyMiddleWareExtensions 
{ 
    public static IApplicationBuilder UseMyMiddleWare(this IApplicationBuilder builder) 
    { 
     return builder.UseMiddleware<MyMiddleWare>(); 
    } 
} 
+0

该示例中的哪个位置是您的自定义中间件?我认为**'UseExeptionHandler'应该能够处理它,但是您的中间件需要在**之后注册**。 – Tseng

回答

5

您应该编写自己的中间件来处理自定义异常处理。并且确保将它添加到中间件堆栈的开头(如果可能,首先),因为在堆栈中“较早”的中间件中发生的异常将不会被处理。

例子:

public class CustomExceptionMiddleware 
{ 
    private readonly RequestDelegate _next; 

    public CustomExceptionMiddleware(RequestDelegate next) 
    { 
     _next = next; 
    } 

    public async Task Invoke(HttpContext context) 
    { 
     try 
     { 
      await _next.Invoke(context); 
     } 
     catch (Exception e) 
     { 
      // Handle exception 
     } 
    } 
} 
+1

'Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware'与您所建议的完全相同。这个中间件recdirects到提供的例外的路径。你可以看到代码https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/ExceptionHandler/ExceptionHandlerMiddleware。cs – LP13

5

你可以用它来处理异常UseExceptionHandler(),把这段代码在你的 Startup.cs

UseExceptionHandler可用于全局处理异常。您可以获取堆栈跟踪,内部异常和其他异常对象的所有细节。然后你可以在屏幕上显示它们。 Here

在这里你可以阅读更多关于这诊断中间件和找到如何使用IExceptionFilter,并通过创建自己的自定义异常处理程序。

app.UseExceptionHandler(
       options => 
       { 
        options.Run(
         async context => 
         { 
          context.Response.StatusCode = (int) HttpStatusCode.InternalServerError; 
          context.Response.ContentType = "text/html"; 
          var ex = context.Features.Get<IExceptionHandlerFeature>(); 
          if (ex != null) 
          { 
           var err = $"<h1>Error: {ex.Error.Message}</h1>{ex.Error.StackTrace}"; 
           await context.Response.WriteAsync(err).ConfigureAwait(false); 
          } 
         }); 
       } 
      ); 

你也必须删除默认设置像UseDeveloperExceptionPage(),如果你使用它,它总是显示默认的错误页面。

if (env.IsDevelopment()) 
     { 
      //This line should be deleted 
      app.UseDeveloperExceptionPage(); 
      app.UseBrowserLink(); 
     } 
     else 
     { 
      app.UseExceptionHandler("/Home/Error"); 
     } 
+0

我以前经历过这篇文章。然而,我认为问题是每当你设置response.StatusCode为500浏览器不显示该服务器发送的HTML,而是浏览器显示它自己的代码500的错误页面。在小提琴手我看到响应正文有错误消息,该服务器发送但浏览器不显示该错误消息。 – LP13

+0

只需从startup.cs中删除app.UseDeveloperExceptionPage(); –

+0

btw我也创建了从'ExceptionFilterAttribute'派生的自定义异常过滤属性。这将处理控制器内的所有异常。我正在寻找中间件的异常处理。即使我使用'app.UseExceptionHandler'全局处理或者创建自己的中间件来处理异常,它也不会将用户重定向到错误视图。 – LP13