• asp.net core之异常处理


    在开发过程中,处理错误是一个重要的方面。ASP.NET Core提供了多种方式来处理错误,以确保应用程序的稳定性和可靠性。

    TryCatch#

    TryCatch是最常见也是最基础的一种异常处理方式,只需要用TryCatch把执行代码包起来,即可捕获异常。
    格式如下:

    try
    {
        // 执行操作
        doAny();
    }
    catch (Exception ex)
    {
        // 处理异常
        doExceptionHandling();
    }
    

    这属于最基本的异常处理方式,这里就不加上实操代码了。本文主要讲解asp.net core中的其他异常处理方式。

    开发人员异常页#

    ASP.NET Core Web应用在以下情况下默认启用开发人员异常页,用于显示未经处理的请求异常的详细信息。
    ASP.NET Core 应用在以下情况下默认启用开发人员异常页:

    • 在开发环境中运行。
    • 使用当前模板创建的应用,即使用 WebApplication.CreateBuilder。 使用 WebHost.CreateDefaultBuilder 创建的应用必须通过在 Configure 中调用 app.UseDeveloperExceptionPage 来启用开发人员异常页。

    开发人员异常页运行在中间件管道的前面部分,以便它能够捕获随后中间件中抛出的未经处理的异常。
    这里我们新建一个MVC项目,使用WebApplication.CreateBuilder,所以不需要显式调用app.UseDeveloperExceptionPage 来启用开发人员异常页,在HomeController中添加一个Thorw方法直接抛出异常:

    using LearnException.Models;
    using Microsoft.AspNetCore.Mvc;
    using System.Diagnostics;
    
    namespace LearnException.Controllers
    {
        public class HomeController : Controller
        {
            private readonly ILogger _logger;
    
            public HomeController(ILogger logger)
            {
                _logger = logger;
            }
    
            public IActionResult Index()
            {
                return View();
            }
    
            public IActionResult Privacy()
            {
                return View();
            }
            public IActionResult Throw()
            {
                throw new Exception("Customer Excetion");
            }
    
            [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
            public IActionResult Error()
            {
                return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
            }
        }
    }
    

    启动项目,然后访问/Home/Throw路径。
    image.png
    可以看到这个页面可以看到我们的详细错误信息,包括异常栈,Query参数, Cookies参数,HTTP请求Headers信息以及路由信息。
    这个页面在开发阶段,非常利于我们排查错误。

    异常处理程序页#

    由于我们的一些异常信息不便在非开发环境展示,所以在非开发环境,我们需要一个异常处理程序页。
    若要为生产环境配置自定义错误处理页,请调用 UseExceptionHandler。 此异常处理中间件:

    • 捕获并记录未经处理的异常。
    • 使用指示的路径在备用管道中重新执行请求。 如果响应已启动,则不会重新执行请求。 模板生成的代码使用 /Home/Error 路径重新执行请求。

    在我们创建的MVC模板的Program中,有这样的代码:

    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Home/Error");
    }
    

    表示在非开发环境中启用此异常处理中间件。这里的"/Home/Error"表示跳转到该路由。该路由为异常处理页面。
    在模板Views/Shared下面我们可以看到一个Error.cshtml,和Models下面有一个ErrorViewModel,这就是默认的异常处理程序页。
    在上面HomeController的代码中我们可以看到一个Error的Action,此Action指向Error页面。我们试试直接起启用app.UseExceptionHandler("/Home/Error"),放开在非开发环境才使用的条件:

    //if (!app.Environment.IsDevelopment())
    //{
        app.UseExceptionHandler("/Home/Error");
    //}
    

    分别请求/Home/Error和/Home/Throw路径
    image.png
    image.png
    可以看到/Home/Throw也是跳转到Error页面,但是没有详细的异常信息。

    自定义异常处理程序页#

    除了上述的方式,我们在需要自定义异常处理程序页时,可以使用app.UseExceptionHandler的另一个重载方法:

    app.UseExceptionHandler(exceptionHandlerApp =>
        {
            exceptionHandlerApp.Run(async context =>
            {
                context.Response.StatusCode = StatusCodes.Status500InternalServerError;
    
                // using static System.Net.Mime.MediaTypeNames;
                context.Response.ContentType = Text.Plain;
    
                await context.Response.WriteAsync("An exception was thrown.");
    
                var exceptionHandlerPathFeature =
                    context.Features.Get();
    
                if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
                {
                    await context.Response.WriteAsync(" The file was not found.");
                }
    
                if (exceptionHandlerPathFeature?.Path == "/")
                {
                    await context.Response.WriteAsync(" Page: Home.");
                }
            });
        });
    

    在上面代码中exceptionHandlerApp是一个IApplicationBuilder,本质是添加一个终结点中间件去处理响应内容,上面内容包括了修改Http响应的StatusCode,ContentType,以及响应内容。
    我们在HomeController中继续添加一个FileNotFound的Action。

    public IActionResult FileNotFound()
    {
    	throw new FileNotFoundException();
    }
    

    启动项目,分别请求/Home/Throw和/Home/FileNotFound。
    image.png
    image.png
    可以看到,响应内容和我们配置的一致。
    由上面表现,其实我们可以想到,如何自定义一个异常处理中间件。

     public class MyExceptionMiddleware
    {
        private readonly RequestDelegate _next;
    
        public MyExceptionMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            try
            {
                await _next(context);
            }
            catch (Exception ex)
            {
                context.Response.StatusCode = StatusCodes.Status500InternalServerError;
    
                // using static System.Net.Mime.MediaTypeNames;
                context.Response.ContentType = Text.Plain;
    
                await context.Response.WriteAsync("An exception was thrown.");
    
    
                if (ex is FileNotFoundException)
                {
                    await context.Response.WriteAsync(" The file was not found.");
                }
            }
        }
    }
    

    在Program添加中间件

    app.UseMiddleware();
    

    image.png
    可以看到,效果完全一致。
    除此之外,我们还有使用ExceptionFilter的方式去处理异常,只要实现实现 IExceptionFilter 或 IAsyncExceptionFilter即可。
    添加一个MyExceptionFilter

    public class MyExceptionFilter : IAsyncExceptionFilter
    {
        public async Task OnExceptionAsync(ExceptionContext context)
        {
            context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
    
            // using static System.Net.Mime.MediaTypeNames;
            context.HttpContext.Response.ContentType = Text.Plain;
    
            await context.HttpContext.Response.WriteAsync("An exception was thrown. by MyExceptionFilter");
        	context.ExceptionHandled = true;
        }
    }
    

    在HomeController添加一个Filter的Action。

    [TypeFilter(typeof(MyExceptionFilter))]
    public IActionResult Filter()
    {
        throw new Exception("MyExceptionFilter Excetion");
    }
    

    启动项目,访问/Home/Filter路径。
    image.png
    可以看到效果跟预想的一致。

    ASP.NET Core提供了多种方式来处理错误。开发人员可以根据具体的需求选择适合的错误处理方式,并进行相应的处理和响应。通过合理的错误处理,可以提高应用程序的稳定性和可靠性,提供更好的用户体验。

    欢迎进群催更。

    image.png

  • 相关阅读:
    mysql 字段用了关键字, 无法插入更新数据
    最优化基础知识总结(1)
    今年三下乡社会实践活动向媒体投稿我有了底气
    insightface 换脸
    RabbitMQ中VirtualHost相关设置、SpringBoot中集成常见问题总结
    锐捷Ruijie路由器版本升级
    Java集训(算法&&面试题)第八天(栈与队列)
    统一使用某一个包管理工具,比如yarn pnpm
    飞行动力学 - 第33节-螺旋模态机理 之 基础点摘要
    剑指 Offer 12. 矩阵中的路径
  • 原文地址:https://www.cnblogs.com/fanshaoO/p/17603536.html