关于c#:处理asp.net核心中的异常?

Handling exception in asp.net core?

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

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

如果中间件有异常,我如何将用户重定向到"错误"页面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
     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
我在上面的代码中更新了以下两行,而这两行在最初的帖子中是缺失的。

1
2
        app.UseSession();
        app.UseMyMiddleware();

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

我不确定这是否是解决此问题的正确方法,但尚无法解决。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
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>();
    }
 }


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

UseExceptionHandler can be used to handle exceptions globally. You can get all the details of exception object like Stack Trace, Inner exception and others. And then you can show them on screen. Here

在这里,您可以了解有关此诊断中间件的更多信息,并找到如何使用IExceptionFilter以及通过创建自己的自定义异常处理程序。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
   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 = $"Error: {ex.Error.Message}{ex.Error.StackTrace}";
                                await context.Response.WriteAsync(err).ConfigureAwait(false);
                            }
                        });
                }
            );

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

1
2
3
4
5
6
7
8
9
10
   if (env.IsDevelopment())
        {
            //This line should be deleted
            app.UseDeveloperExceptionPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }


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

例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
        }
    }
}