tnblog
首页
视频
资源
登录

异常处理中间件:区分真异常与逻辑异常

6082人阅读 2020/7/30 15:10 总访问:3667522 评论:1 收藏:0 手机
分类: .net后台框架

.netcore

异常处理中间件:区分真异常与逻辑异常


处理异常的方式

  • 异常处理页
  • 异常处理匿名委托方法
  • IExceptionFilter
  • ExceptionFilterAttribute

Demo

项目结构

项目结构

创建相关Model


IKnownException.cs
  1. public interface IKnownException
  2. {
  3. public string Message { get; }
  4. public int ErrorCode { get; }
  5. public object[] ErrorData { get; }
  6. }
KnownException.cs
  1. public class KnownException : IKnownException
  2. {
  3. public string Message { get; private set; }
  4. public int ErrorCode { get; private set; }
  5. public object[] ErrorData { get; private set; }
  6. public readonly static IKnownException Unknown = new KnownException { Message = "未知错误", ErrorCode = 9999 };
  7. public static IKnownException FromKnownException(IKnownException exception)
  8. {
  9. return new KnownException { Message = exception.Message, ErrorCode = exception.ErrorCode, ErrorData = exception.ErrorData };
  10. }
  11. }
MyExceptionFilter.cs
  1. public class MyExceptionFilter : IExceptionFilter
  2. {
  3. public void OnException(ExceptionContext context)
  4. {
  5. IKnownException knownException = context.Exception as IKnownException;
  6. if (knownException == null)
  7. {
  8. var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
  9. logger.LogError(context.Exception, context.Exception.Message);
  10. knownException = KnownException.Unknown;
  11. context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
  12. }
  13. else
  14. {
  15. knownException = KnownException.FromKnownException(knownException);
  16. context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
  17. }
  18. context.Result = new JsonResult(knownException)
  19. {
  20. ContentType = "application/json; charset=utf-8"
  21. };
  22. }
  23. }
MyServerException.cs
  1. public class MyServerException : Exception, IKnownException
  2. {
  3. public MyServerException(string message, int errorCode, params object[] errorData) : base(message)
  4. {
  5. this.ErrorCode = errorCode;
  6. this.ErrorData = errorData;
  7. }
  8. public int ErrorCode { get; private set; }
  9. public object[] ErrorData { get; private set; }
  10. }

创建错误处理MyExceptionFilterAttribute.cs过滤器

  1. public class MyExceptionFilterAttribute : ExceptionFilterAttribute
  2. {
  3. public override void OnException(ExceptionContext context)
  4. {
  5. IKnownException knownException = context.Exception as IKnownException;
  6. if (knownException == null)
  7. {
  8. var logger = context.HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
  9. logger.LogError(context.Exception, context.Exception.Message);
  10. knownException = KnownException.Unknown;
  11. context.HttpContext.Response.StatusCode = StatusCodes.Status500InternalServerError;
  12. }
  13. else
  14. {
  15. knownException = KnownException.FromKnownException(knownException);
  16. context.HttpContext.Response.StatusCode = StatusCodes.Status200OK;
  17. }
  18. context.Result = new JsonResult(knownException)
  19. {
  20. ContentType = "application/json; charset=utf-8"
  21. };
  22. }
  23. }

创建错误处理ErrorController.cs控制器

  1. [AllowAnonymous]
  2. public class ErrorController : Controller
  3. {
  4. [Route("/error")]
  5. public IActionResult Index()
  6. {
  7. var exceptionHandlerPathFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
  8. var ex = exceptionHandlerPathFeature?.Error;
  9. var knownException = ex as IKnownException;
  10. if (knownException == null)
  11. {
  12. var logger = HttpContext.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
  13. logger.LogError(ex, ex.Message);
  14. knownException = KnownException.Unknown;
  15. }
  16. else
  17. {
  18. knownException = KnownException.FromKnownException(knownException);
  19. }
  20. return View(knownException);
  21. }
  22. }

创建报错方法


WeatherForecastController.cs
  1. [ApiController]
  2. [Route("[controller]")]
  3. public class WeatherForecastController : ControllerBase
  4. {
  5. [HttpGet]
  6. public int Get()
  7. {
  8. throw new MyServerException("服务出错了", 65);
  9. }
  10. }

通过控制器处理错误


修改Startup.csConfigure方法,添加处理异常路径

  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  2. {
  3. app.UseExceptionHandler("/error");
  4. app.UseRouting();
  5. app.UseAuthorization();
  6. app.UseEndpoints(endpoints =>
  7. {
  8. endpoints.MapControllers();
  9. });
  10. }

注意请修改ConfigureServices方法

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc();//.AddControllers();
  4. }

运行结果

通过委托的方式处理错误


修改Startup.csConfigure方法

  1. public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
  2. {
  3. app.UseExceptionHandler(errApp =>
  4. {
  5. errApp.Run(async context =>
  6. {
  7. var exceptionHandlerPathFeature = context.Features.Get<IExceptionHandlerPathFeature>();
  8. IKnownException knownException = exceptionHandlerPathFeature.Error as IKnownException;
  9. if (knownException == null)
  10. {
  11. var logger = context.RequestServices.GetService<ILogger<MyExceptionFilterAttribute>>();
  12. logger.LogError(exceptionHandlerPathFeature.Error, exceptionHandlerPathFeature.Error.Message);
  13. knownException = KnownException.Unknown;
  14. context.Response.StatusCode = StatusCodes.Status500InternalServerError;
  15. }
  16. else
  17. {
  18. knownException = KnownException.FromKnownException(knownException);
  19. context.Response.StatusCode = StatusCodes.Status200OK;
  20. }
  21. var jsonOptions = context.RequestServices.GetService<IOptions<JsonOptions>>();
  22. context.Response.ContentType = "application/json; charset=utf-8";
  23. await context.Response.WriteAsync(System.Text.Json.JsonSerializer.Serialize(knownException, jsonOptions.Value.JsonSerializerOptions));
  24. });
  25. });
  26. app.UseRouting();
  27. app.UseAuthorization();
  28. app.UseEndpoints(endpoints =>
  29. {
  30. endpoints.MapControllers();
  31. });
  32. }

运行结果(这里有部分乱码)

通过过滤器的方式处理错误


Configure方法

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddMvc(mvcOptions =>
  4. {
  5. //mvcOptions.Filters.Add<MyExceptionFilter>();
  6. mvcOptions.Filters.Add<MyExceptionFilterAttribute>();
  7. }).AddJsonOptions(jsonoptions =>
  8. {
  9. jsonoptions.JsonSerializerOptions.Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
  10. });
  11. }

运行结果

异常处理技巧

  • 用特定的异常类活接口表示业务逻辑异常
  • 为业务逻辑异常定义全局错误码
  • 为未知异常定义特定的输出信息和错误码
  • 对于已知业务逻辑异常响应 HTTP 200(监控系统友好)
  • 对于未预见的异常响应 HTTP 500
  • 为所有的异常记录详细的日志

欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

bk

2020/7/30 22:27:58

[good][good][good][good]

Idea下使用maven搭建SSM(一)SpringMVC

Spring MVC是一款基于MVC架构模式的轻量级Web框架,其目的是将Web开发模块化,对整体架构进行解耦,简化Web开发流程。下面...

Idea下使用maven搭建SSM(二)MyBatis

开发Web应用,数据的存储和处理往往离不开数据库和SQL语句。在使用Java开发的Web应用中,自然也少不了连接数据库的步骤。在...

c webservice一基本使用

什么是webserviceWebservie是一种网络服务是一种与语言无关的服务webserver主要作用:1:可以跨平台跨语言访问2:可以做SOA...

c webservice二基本分布式访问

使用webservice接口有个好处就是可以分布式访问。例如我们在玩游戏的时候先要选择一个区,然后在进入游戏。这样是因为如果...

mysql 存储过程报错delimiter

最近刚学sql,学到了存储过程,每当练习的时候就一直出现问题。 现在记录CREATEPROCEDUREproc_out(OUTstuidINT) begin se...

推荐一款三无压缩软件bandizip

哈喽,大家好,我是刘小贱相信大家作为程序员的一员,都在使用压缩软件,但是呢我们常常使用的压缩软件都有很多的弊端,不但对...

解决基础提供程序在 Open 上失败,EF无法生成实体问题

在学校图书馆的电脑上安装VS2013和SQL R2后,调试项目报错:基础提供程序在 Open 上失败怀疑是数据库的问题,然后删除数据...

系统重装(一)安装制作Windows原装系统U盘

Windows是美国微软公司研发的跨平台及设备应用的操作系统.xinXP已经停止更新,微软也将在2020年1月14日正式结束对Windows 7...

Spring Cloud+.Net Core搭建微服务架构 一服务注册

在微服务中,不同的业务被拆分成不同的服务,不同的服务之间会相互依赖,而管理这些服务就变得尤为重要搭建服务注册中心服...

.NET MVC 使用百度编辑器详细教程(1)配置编辑器

一、什么是百度编辑器百度编辑器UEditor是由百度web前端研发部开发一款应用于网站的编辑器,具有轻量,可定制,注重用户体...

解决iframe登录过期跳转登录页面嵌套问题

我们在登录信息过期之后,要跳转到登录页面。这时如果你用的是iframe框架的话,就会出现登录界面是嵌套在框架里面的,如下...

ASP.NET MVC + WebUploader实现文件上传二使用中的一些问题

如何把文件选择按钮换成自己的因为WebUploader设置关联的上传id会有他的样式,有时候想换成自己的开始想的是添加自己的文件...

Xamarin android.permission.CALL_PHONE 的权限问题

写个电话拨号器,很简单就一个Edittext和一个button,用来输入号码并且点击按钮拨打电话,但是写好以后报的是安全错误,我上...

系统重装(二)安装Windows系统

嗨,大家好!上一篇我们介绍了如何制作windows系统U盘,这一篇就来介绍一下如何安装。上一篇链接请点击:http://www.tnblog...

mui学习二 调试状态看console.log等

看console.log上面点击一下即可也可以在浏览器上看把连接复制上去即可这样就可以了
这一世以无限游戏为使命!
排名
2
文章
657
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 : 好是好,这个对效率影响大不大哇,效率高不高
ASP.NET Core 服务注册生命周期
剑轩 : http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术