2016-11-15 2 views
7

У меня есть приложение asp.net core. Реализация метода configure перенаправляет пользователя на страницу «Ошибка» при возникновении исключения (в среде без разработки)Обработка исключения в ядре 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?}"); 
     }); 
    } 

Update 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' делает то же самое, что вы предложили. Это промежуточное программное обеспечение перенаправляет на предоставленный путь для исключения. Вы можете увидеть код https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/ExceptionHandler/ExceptionHandlerMiddleware.cs – LP13

5

Вы можете использовать для обработки исключений UseExceptionHandler(), поместите этот код в Startup.cs.

UseExceptionHandler может использоваться для обработки исключений по всему миру. Вы можете получить все детали объекта исключения, такие как Stack Trace, Inner exception и другие. И затем вы можете показать их на экране. 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