处理asp.net核心中的异常?

LP1*_*P13 16 c# asp.net-core-mvc coreclr asp.net-core

我有asp.net核心应用程序.当存在异常时(在非开发环境中),configure方法的实现将用户重定向到"Error"页面

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

如果中间件中存在异常,如何将用户重定向到"错误"页面.

     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?}");
        });
    }
Run Code Online (Sandbox Code Playgroud)

更新1
我更新了上面的代码,其中包含初始帖子中缺少的以下两行.

        app.UseSession();
        app.UseMyMiddleware();
Run Code Online (Sandbox Code Playgroud)

另外我发现为什么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>();
    }
 }
Run Code Online (Sandbox Code Playgroud)

M. *_*cki 20

您可以使用它来处理异常UseExceptionHandler(),将此代码放入您的代码中 Startup.cs.

UseExceptionHandler可用于全局处理异常.您可以获取异常对象的所有详细信息,如Stack Trace,Inner异常等.然后你可以在屏幕上显示它们. 这里

在这里您可以阅读有关此诊断中间件的更多信息,并了解如何使用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);
                            }
                        });
                }
            );
Run Code Online (Sandbox Code Playgroud)

您还必须删除默认设置UseDeveloperExceptionPage(),如果您使用它,它始终显示默认错误页面.

   if (env.IsDevelopment())
        {
            //This line should be deleted
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }
Run Code Online (Sandbox Code Playgroud)

  • 是否可以将 UseExceptionHandler 与默认错误页面一起使用?我想捕获错误详细信息,但保留现有的行为和页面。 (3认同)
  • 只需从 startup.cs app.UseDeveloperExceptionPage() 中删除; (2认同)
  • @LP13 你需要删除 app.UseDeveloperExceptionPage(); 这将是工作。 (2认同)

And*_*ius 6

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

例:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware`与你建议的完全一样.此中间件会重新定向到提供的路径,例外情况.你可以看到代码https://github.com/aspnet/Diagnostics/blob/dev/src/Microsoft.AspNetCore.Diagnostics/ExceptionHandler/ExceptionHandlerMiddleware.cs (2认同)