.net 怎么在控制器action中返回一个试图_ASP.NET Core MVC/WebAPI中另辟蹊径的全局统一异常处理方式...
作为一名合格的.NET开发者,大家都知道在程序发生异常的时候,不应该将详细的异常堆栈信息抛给前台用户显示,我们应该对程序所有的不可预知的异常做统一处理,返回一个有好的提示给前台用户,并在程序里将错误信息以日志的形式记录下来,比如一个友好的错误页面,像我自己网站的404页面和503页面:
相信大家对统一异常处理都比较熟悉,可以通过自己实现一个异常拦截的中间件实现,也可以实现一个FilterAttribute对所有的控制器进行异常拦截,这都是比较常见的异常处理方式,但以上两种,如果想在程序出现错误时,不发生路由跳转直达错误页,有时候还是不太方便,所以,今天给大家另辟蹊径分享一个全局异常的同一拦截处理方式,发生错误时,页面路由不会发生跳转。
那就是微软自己提供的——UseExceptionHandler中间件。
开始打码实现吧
为了方便演示,我先搭建一个基础的http://ASP.NET Core项目,并创建了一个HomeController:
public class HomeController : Controller{// GETpublic IActionResult Index(){return Ok("这是首页");}[HttpGet("test")]public ActionResult Test(){throw new Exception("手动发生一个异常");}}
再创建一个ErrorController控制器,并写一个Action来作为我们的错误页面:
[Route("error")]public class ErrorController : Controller{[HttpGet]public IActionResult Index(){return Ok("假装是一个错误页面");}}
接下来实现异常处理中间件,该中间件在Startup的Configure方法中注册,需要传入一个路由,而错误页的路由是“/error”,所以注册中间件:
app.UseExceptionHandler("/error");
然后我们运行项目,触发一次异常:
发生异常的时候,确实已经到我们的错误页了,而且路由没有改变,但是,我们没有记录下发生错误时的堆栈信息,为了后期的诊断,我们肯定要记录详细的异常信息才行,那如何将异常信息记录下来呢?
UseExceptionHandler中间件中拦截到异常时,会将异常信息保存在请求上下文中,所以我们可以从HttpContext中拿到ExceptionHandler的异常信息:
var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
如果程序有异常,那么feature是一个不为null的对象,其属性Error便是我们需要的Exception,所以,我们改造一下刚才的ErrorController:
[Route("error")]public class ErrorController : Controller{[HttpGet]public IActionResult Index(){var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();if (feature != null){var exception = feature.Error;// todo:调用日志组件记录异常信息,或对异常做多路判断}return Ok("假装是一个错误页面");}}
比如本站的异常多路处理源码如下:
[Route("ServiceUnavailable")]public ActionResult ServiceUnavailable(){var feature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();if (feature != null){string err;var req = HttpContext.Request;var ip = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();switch (feature.Error){case DbUpdateConcurrencyException ex:err = $"异常源:{ex.Source},异常类型:{ex.GetType().Name},n请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(req.Path)},客户端用户代理:{req.Headers["User-Agent"]},客户端IP:{ip}t{ex.InnerException?.Message}t";LogManager.Error(err, ex);break;case DbUpdateException ex:err = $"异常源:{ex.Source},异常类型:{ex.GetType().Name},n请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(req.Path)},客户端用户代理:{req.Headers["User-Agent"]},客户端IP:{ip}t{ex?.InnerException?.Message}t";LogManager.Error(err, ex);break;case AggregateException ex:LogManager.Debug("↓↓↓" + ex.Message + "↓↓↓");ex.Handle(e =>{LogManager.Error($"异常源:{e.Source},异常类型:{e.GetType().Name},n请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(req.Path)},客户端用户代理:{req.Headers["User-Agent"]},客户端IP:{ip}t", e);return true;});break;case NotFoundException ex:Response.StatusCode = 404;return Request.Method.ToLower().Equals("get") ? (ActionResult)View("Index") : Json(new{StatusCode = 404,Success = false,ex.Message});default:LogManager.Error($"异常源:{feature.Error.Source},异常类型:{feature.Error.GetType().Name},n请求路径:{req.Scheme}://{req.Host}{HttpUtility.UrlDecode(req.Path)},客户端用户代理:{req.Headers["User-Agent"]},客户端IP:{ip}t", feature.Error);break;}}Response.StatusCode = 503;if (Request.Method.ToLower().Equals("get")){return View();}return Json(new{StatusCode = 503,Success = false,Message = "服务器发生错误!"});}
至此,全局异常处理已经完整实现。
总结
相较于自己实现中间件和FilterAttribute,其实这种在控制器中实现异常记录的方式个人感觉更简单且方便,既然微软已经为我们开放了这样的方式,我们为什么不用呢?
网站开源代码:
https://github.com/ldqk/Masuit.MyBlogsgithub.com
转自原文:
ASP.NET Core MVC/WebAPI中另辟蹊径的全局统一异常处理方式masuit.com
.net 怎么在控制器action中返回一个试图_ASP.NET Core MVC/WebAPI中另辟蹊径的全局统一异常处理方式...相关推荐
- .net 怎么在控制器action中返回一个试图_一个view事件分发,面试官6连问直击灵魂,我被虐的体无完肤...
注:原文来自掘金作者xiangcman 写这篇文章其实是有原因的,说实话这次面试真的很失败,看着身边的人都拿到了高薪的工资,感觉自己还是有些惭愧.也更说明自己在很多方面的知识点还是不够扎实,于是再一次 ...
- mysql desc 显示备注_MySQL_Mysql中返回一个数据库的所有表名,列名数据类型备注,desc 表名; show columns from 表名; d - phpStudy...
Mysql中返回一个数据库的所有表名,列名数据类型备注 desc 表名; show columns from 表名; describe 表名; show create table 表名; use in ...
- Pandas中xs()函数索引复合索引数据的不同切面数据(索引复合索引中需要的数据):索引列复合索引中的一个切面、索引行复合索引中的一个切面
Pandas中xs()函数索引复合索引数据的不同切面数据(索引复合索引中需要的数据):索引列复合索引中的一个切面.索引行复合索引中的一个切面 目录
- Spring中Controller层、Filter层、Interceptor层全局统一异常处理
Controller层.Filter层.Interceptor层全局统一异常处理 SpringBoot为异常处理提供了很多优秀的方法,但是像我这种新手在处理异常时还是会觉得一头包,终于我痛定思痛,总结 ...
- C 如何在函数中返回一个数组
int test(int *b) {int source[5]={[1]=2,[3]=4,[4]=-2}; memcpy(b,source,5*sizeof(int));return 0; }int ...
- 在qt中用c语言数组,在QT函数中返回一个数组/把一个数组传参给函数
1.把数组传参给函数 可以定义一个QVector的一个数组 QVector num(10); for(int i =0;i<10;i++) num [i] = i*i; fun(num); / ...
- 如何在 ASP.NET Core MVC 5 中处理未知的 Action
ASP.NET Core MVC 5 是一个轻量级,开源的,利于单元测试的基于 ASP.NET Core 运行时的 web 框架,在开发时你肯定会遇到不少那些 request 无法匹配 Action ...
- python链表中删除一个节点数据_python实现单链表中删除倒数第K个节点的方法
本文实例为大家分享了python实现单链表中删除倒数第K个节点的具体代码,供大家参考,具体内容如下 题目: 给定一个链表,删除其中倒数第k个节点. 代码: class LinkedListAlgori ...
- 在https上面使用ws不加密_ASP.NET Core 3.1 中使用JWT认证
转自:小伟06cnblogs.com/liuww/p/12177272.html JWT认证简单介绍 关于Jwt的介绍网上很多,此处不在赘述,我们主要看看jwt的结构. JWT主要由三部分组成,如下: ...
- java中的 请求体_在spring mvc test中访问请求体和请求头
我创建了一个spring boot应用程序,这就是我的控制器的样子 . 我使用postman在请求体中发送json,在请求头中发送一个字符串,然后进一步散列json并将其与请求头获取的字符串进行比较 ...
最新文章
- LVS的DR工作模型解析
- 蓝桥杯-打印十字图-java
- VTK:可视化之Cursor3D
- poj 3460 bookstore
- C语言中extern修饰符的用法
- Android 获取设备ID,手机厂商,运营商,联网方式,获取系统语言,获取时区
- Oracle client 安装、配置
- (转)VS.NET使用
- javascript textContent与innerText的异同分析
- ubuntu 11.10下载和编译Android源码
- 订餐系统项目中OrderForm、OrderDTO、OrderMaster和ResultVO的区别
- python中dtype什么意思_浅谈python 中的 type(), dtype(), astype()的区别
- Java对二维数组排序
- 笔记本 续航测试软件,续航测试:较高强度运行状态_笔记本评测-中关村在线
- 2021年上半年软件设计师上午真题及答案解析
- web前端开发面试题(七)
- Java处理富文本编辑器的图片转为base64编码
- 如果诸葛亮用C#写出师表...
- PSTN与VoIP相关知识
- Mysql 中的 mvcc原理