Asp.Net Core中5种异常处理方案

作者 the7
发布于 2020年02月13日
评论 0
浏览 411

异常处理在编程中非常重要,一来可以给用户友好提示,二来也是为了程序安全。在Asp.Net Core中,默认已经为我们了提供很多解决方案,下面就来总结一下。

一,继承Controller,重写OnActionExecuted

使用vs新建controller时,默认都会继承一个Controller类,重写OnActionExecuted,添加上异常处理即可。一般情况下我们会新建一个BaseController, 让所有Controller继承BaseController。代码如下

public class BaseController : Controller
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var exception = context.Exception;
        if (exception != null)
        {
            context.ExceptionHandled = true;
            context.Result = new ContentResult
            {
                Content = $"BaseController错误 : { exception.Message }"
            };
        }
        base.OnActionExecuted(context);
    }
}

这种处理方式优点当然是简单,缺点也很明显,如果cshtml页面抛错,就完全捕获不了。当然如果项目本身就是一个web api 项目,没有view,这还是可以的。

二,使用 ActionFilterAttribute

ActionFilterAttribute是一个特性,本身实现了 IActionFilterIResultFilter , 所以不管是action里抛错,还是view里抛错,理论上都可以捕获。我们新建一个 ExceptionActionFilterAttribute, 重写 OnActionExecutedOnResultExecuted,添加上异常处理,完整代码如下。

public class ExceptionActionFilterAttribute:ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        var exception = context.Exception;
        if (exception != null)
        {
            context.ExceptionHandled = true;
            context.Result = new ContentResult
            {
                Content = $"错误 : { exception.Message }"
            };
        }
        base.OnActionExecuted(context);
    }

    public override void OnResultExecuted(ResultExecutedContext context)
    {
        var exception = context.Exception;
        if (exception != null)
        {
            context.ExceptionHandled = true;
            context.HttpContext.Response.WriteAsync($"错误 : {exception.Message}");
        }
        base.OnResultExecuted(context);
    }
}

使用方式有两种,

  1. 在controller里打上 [TypeFilter(typeof(ExceptionActionFilter)] 标签。
  2. 在Startup里以filter方式全局注入。
    services.AddControllersWithViews(options =>
    {
        options.Filters.Add<ExceptionActionFilterAttribute>();
    })
    

三,使用 IExceptionFilter

我们知道, Asp.Net Core提供了5类filter, IExceptionFilter是其中之一,顾名思义,这就是用来处理异常的。Asp.net Core中ExceptionFilterAttribute已经实现了IExceptionFilter,所以我们只需继承ExceptionFilterAttribute,重写其中方法即可。 同样新建CustomExceptionFilterAttribute继承 ExceptionFilterAttribute,重写 OnException ,添加异常处理,完整代码如下

public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
    public override void OnException(ExceptionContext context)
    {
        context.ExceptionHandled = true;
        context.HttpContext.Response.WriteAsync($"CustomExceptionFilterAttribute错误:{context.Exception.Message}");
        base.OnException(context);
    }
}

注意,ExceptionFilterAttribute还提供了异步方法OnExceptionAsync,这两个处理方法,只需重写一个即可,如果两个都重写,两个方法都会执行一次。

使用方式有两种,

  1. 在controller里打上 [CustomExceptionFilter] 标签。
  2. 在Startup里以filter方式全局注入。
    services.AddControllersWithViews(options =>
    {
        options.Filters.Add<CustomExceptionFilterAttribute>();
    })
    

四,使用ExceptionHandler

在 startup 里,vs新建的项目会默认加上

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
}
else
{
    app.UseExceptionHandler("/Home/Error");
}

上边这段代码,大意为:开发环境使用app.UseDeveloperExceptionPage(); 。生产环境会跳转至 home/error 页面。
UseDeveloperExceptionPage 会给出具体错误信息,具体包括 Stack trace、Query、Cookies、Headers 四部分。.net core 3.1后有些改动,如果请求头加上 accept:text/html, 就返回html页面,不加的话,只会返回错误。

注意:app.UseDeveloperExceptionPage(); 应该置于最前边。

   if (!env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler(builder =>
        {
            builder.Run(async context =>
            {
                var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
                await context.Response.WriteAsync($"error:{exceptionHandlerPathFeature.Error.Message}");
            });
        });
    }

五,自定义Middleare处理

通过middleware全局处理。

public class ErrorHandlingMiddleware
{
   private readonly RequestDelegate next;

   public ErrorHandlingMiddleware(RequestDelegate next)
   {
        this.next = next;
   }

   public async Task Invoke(HttpContext context)
   {
        try
        {
           await next(context);
        }
        catch (System.Exception ex)
        {
           //处理异常
        }
   }
}

0条评论

请先登录后发表评论
提交评论
标签云
css (1) less calc (1) C# (4) C#进制转换 (1) asp.net core (8) Authentication (1) 注销 (1) 登录 (1) 验证 (1) scroll-view (1) 微信小程序 (4) 滚动到底部 (1) StackExchange.Redis (1) google (1) 百度 (1) nginx (2) 大文件 (2) 微信小程序c#解密 (1) 微信小程序获取手机号 (1) openid (1) session_key (1) CDN (1) URL鉴权 (1) 阿里云 (1) async (1) await (1) 禁止下拉上滑效果 (1) Index类型 (1) Range类型 (1) dontent publish (1) dotnet publish在线生成器 (1) System.DrawingCore.GDIPlus报错 (1) centos (1) 中文字体 (1) SqlBulkCopy (1) SqlSugar (1) JWT (5) 认证 (3) RSA JWT (1) 非对称加密 (1) 写信 (1) 见字如面 (1) 优化建议 (2) 正确操作字符串 (1) Java (1) JWT退出 (1) RefreshToken (1) .NET Core网站开发框架 (1) Moz (3) 墨子 (1) JSON.NET (1) Newtonsoft (1) System.Text.Json (1) 自定义后台路径 (1) .netcore (1) quartz (2) 作业调度框架 (1) 作业调度 (1) 定时任务 (1) exception (1) 异常处理 (1) HttpClient (1) IHttpClientFactory (1) RDM (1) Redis (1) Redis Desktop Manager (1) RedisDesktopManager (1) linux (1) mac (1) windows (1) Could not get any response (1) postman (1) leetcode (2) 力扣 (1) 回文字符串 (1) 面试刷题 (1) centos7 (1) php安装 (1) 网易云插件 (1) 马甲App (1) Discuz插件 (1) 网易云音乐 (1) Blazor (1) 五子棋 (1) c#解题 (1) 最长连续序列 (1) Swagger (1) 在线文档 (1) blob (1) mp4 (1) 视频 (1) big file (1) 上传 (1) s (1) Azure (1) Azure Key Vault (1) Configuration (1) 密钥保管库 (1) Dapper安装 (1) Dapper是什么 (1) Dapper连接Mysql (1) Dapper连接SqlServer (1) dapper (1)