2016-11-15 95 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