异常是一种运行时错误,当异常没有得到适当的处理,很可能会导致你的程序意外终止,这篇就来讨论一下如何在 ASP.Net Core MVC 中实现全局异常处理,我会用一些 样例代码 和 截图 来说明这些概念。

全局异常处理

其实在 ASP.Net Core MVC 框架中已经有了全局异常处理的机制,你可以在一个中心化的地方使用 全局异常处理中间件 来进行异常拦截,如果不用这种中心化方式的话,你就只能在 Controller 或者 Action 作用域上单独处理,这会导致异常处理代码零散在项目各处,不好维护也特别麻烦,不是吗?

第二种处理 全局异常 的做法就是使用 exception filter,在本篇中,我准备跟大家聊一聊 全局异常处理中间件UseExceptionHandler 方法来管控异常。

使用 UseExceptionHandler 扩展方法

UseExceptionHandler 扩展方法能够将 ExceptionHandler 中间件注册到 Asp.net Core 的 请求处理管道 中,然后在 IExceptionHandlerFeature 接口的实例中获取 异常对象,下面的代码片段展示了如何使用 UseExceptionHandler 方法来截获全局异常。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env){app.UseExceptionHandler(builder =>{builder.Run(async context =>{context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;context.Response.ContentType = "application/json";var exception = context.Features.Get<IExceptionHandlerFeature>();if (exception != null){var error = new ErrorMessage(){Stacktrace = exception.Error.StackTrace,Message = exception.Error.Message};var errObj = JsonConvert.SerializeObject(error);await context.Response.WriteAsync(errObj).ConfigureAwait(false);}});});app.UseStaticFiles();app.UseRouting();app.UseAuthorization();app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");});}

下面是代码中引用的 ErrorMessage 类的定义。

public class ErrorMessage{public string Message { get; set; }public string Stacktrace { get; set; }}

配置 全局异常中间件

大家都知道,ASP.Net Core MVC 项目中都会有一个 Startup.cs 文件,可以在 Configure 方法下配置 全局异常拦截中间件 代码,如下所示:

public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Error");}app.UseStaticFiles();app.UseCookiePolicy();app.UseMvc(routes =>{routes.MapRoute(name: "default",template:"{controller=Home}/{action=Index}/{id?}");});}

可以着重看一下上面的 app.UseExceptionHandler("/Error");,这里的 UseExceptionHandler 实现了 pipeline 注册,一旦应用程序出现了未处理异常,那么会自动将 用户 导向 /Error 页面。

你可以用 UseStatusCodePagesWithReExecute 扩展方法给 pipeline 添加一些状态码页面,这是什么意思呢?其实也就是 http 500 导向 500 页面, http 404 导向 404 页面,下面的代码片段展示了修改后的 Configure 方法代码。

public void Configure(IApplicationBuilder app, IHostingEnvironment env){if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}else{app.UseExceptionHandler("/Error");app.UseStatusCodePagesWithReExecute("/Error/NotFound/{0}");}//Other code}

使用 ErrorController

在 HomeController 下有一个专门处理错误的 action 方法,这里我们不使用这个 action,你可以把它删掉,接下来我准备定义一个专门的 ErrorController,里面包含了一个路由为 /Error 的 action 方法。

public class ErrorController : Controller{[HttpGet("/Error")]public IActionResult Index(){IExceptionHandlerPathFeature iExceptionHandlerFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();if (iExceptionHandlerFeature != null){string path = iExceptionHandlerFeature.Path;Exception exception = iExceptionHandlerFeature.Error;//Write code here to log the exception detailsreturn View("Error",iExceptionHandlerFeature);}                return View();}[HttpGet("/Error/NotFound/{statusCode}")]public IActionResult NotFound(int statusCode){var iStatusCodeReExecuteFeature =HttpContext.Features.Get<IStatusCodeReExecuteFeature>();return View("NotFound",iStatusCodeReExecuteFeature.OriginalPath);}}

你可以用 IExceptionHandlerPathFeature 来获取异常相关信息,也可以用 IStatusCodeReExecuteFeature 来获取 http 404 异常时当时的请求路径,对了,要想用上 IExceptionHandlerPathFeatureIStatusCodeReExecuteFeature,要记得在 nuget 上安装了 Microsoft.AspNetCore.Diagnostics 包,下面的代码展示了如何获取异常发生时刻的路由地址。


string route = iExceptionHandlerFeature.Path;

如果想获取异常的详细信息,可以使用如下语句。


var exception = HttpContext.Features.Get<IExceptionHandlerPathFeature>();

一旦获取了这个路由地址和异常的详细信息,就可以将它记录到你的日志文件中,可供后续仔细分析。

使用 View 展示错误信息

可以创建一个 View 来展示出现的错误信息,下面时 Error ViewPage 的详细代码。


@model Microsoft.AspNetCore.Diagnostics.IExceptionHandlerFeature
@{ViewData["Title"] = "Index";Layout = "~/Views/Shared/_Layout.cshtml";
}
<div class="row"><div class="text-danger"><h3>Error: @Model.Error.Message</h3></div>
</div>
<div class="row"><div class="col-12"><p>@Model.Error.StackTrace</p><p>@Model.Error.InnerException</p></div>
</div>

下面是 NotFound 页面的 代码


@model string
@{ViewData["Title"] = "NotFound";Layout = "~/Views/Shared/_Layout.cshtml";
}<h1 class="text-danger">Error: The requested URL @Model was not found!</h1>
<hr />

现在可以把程序跑起来了,你会看到如下的错误信息。

如果你尝试打开一个不存在的页面, 会自动跳转到 ErrorController.NotFound 所包装的 404 描述信息。

ASP.NET Core 中内置了 全局异常处理,你可以利用这项技术在一个集中化的地方去截获你应用程序中的所有异常信息,当然你也可以基于环境的不同采取不用的异常处理措施,比如说:开发环境,测试环境,生产环境 等等。

译文链接:https://www.infoworld.com/article/3435771/how-to-implement-global-exception-handling-in-aspnet-core-mvc.html

如何在 ASP.NET Core 中实现全局异常拦截相关推荐

  1. 获取异常信息_如何在 ASP.NET Core 中实现全局异常拦截

    异常是一种运行时错误,当异常没有得到适当的处理,很可能会导致你的程序意外终止,这篇就来讨论一下如何在 ASP.Net Core MVC 中实现全局异常处理,我会用一些 样例代码 和 截图 来说明这些概 ...

  2. 如何在 ASP.NET Core 中使用 HttpClientFactory ?

    ASP.Net Core 是一个开源的,跨平台的,轻量级模块化框架,可用它来构建高性能的Web程序,这篇文章我们将会讨论如何在 ASP.Net Core 中使用 HttpClientFactory. ...

  3. 如何在 ASP.Net Core 中使用 Autofac

    依赖注入可以有效的实现对象之间的 松耦合 并能够实现代码的可测试和可维护性,ASP.Net Core 提供了一个极简版的容器实现对 依赖注入 的原生支持,然而内置的依赖注入容器相比成熟的 依赖注入容器 ...

  4. 如何在 ASP.Net Core 中使用 Lamar

    ASP.Net Core 自带了一个极简的 开箱即用 的依赖注入容器,实际上,你还可以使用第三方的 依赖注入容器 来替代它,依赖注入是一种设计模式,它能够有效的实现对象之间的解耦并有利于提高单元测试和 ...

  5. 如何在 ASP.Net Core 中使用 MediatR

    MediatR 是一个 中介者模式 的.NET开源实现, 中介者模式 管控了一组对象之间的相互通讯并有效的减少了对象之间错综复杂的相互依赖,在 中介者模式 中,一个对象不需要直接和另一个对象进行通讯, ...

  6. 如何在 ASP.Net Core 中对接 WCF

    在 REST API 出现之前,SOAP (Simple Object Access Protocol) 一直都是基于 web 的标准协议,虽然现在 REST 大行其道,但在平时开发中总会遇到对接第三 ...

  7. 如何在 ASP.Net Core 中使用 NCache

    虽然 ASP.Net Core 中缺少 Cache 对象,但它引入了三种不同的cache方式. 内存缓存 分布式缓存 Response缓存 Alachisoft 公司提供了一个开源项目 NCache, ...

  8. 如何在 ASP.Net Core 中使用 Configuration Provider

    ASP.NET Core 是一个开源的,跨平台的,精简的模块化框架,可用于构建高性能,可扩展的web应用程序, ASP.NET Core 中的数据配置常用 k-v 的形式存储,值得注意的是,新的数据配 ...

  9. 如何在 ASP.Net Core 中使用 Serilog

    记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...

最新文章

  1. Nature:全球表层土微生物组群落结构和功能
  2. JavaScript 高级篇之DOM文档,简单封装及调用、动态添加、删除样式(推荐七)
  3. htc d10w android 7.0,LineageOS 17.1即将发布:基于Android 10,大量老款手机支持
  4. m3u8链接地址_FFmpeg下载m3u8视频
  5. Java之链表的反转
  6. 20211111C++练习总结
  7. 扫读笔好还是点读笔好 有什么区别
  8. 【ArcGIS】PointsToLine执行报999999错误的一种解决方案
  9. 转:创业者一手货:我是怎么在网上卖鱼的?
  10. page_to_pfn 、virt_to_page、 virt_to_phys、page、页帧pfn、内核虚拟地址、物理内存地址linux内核源码详解
  11. 30分钟快速生成元宇宙专属虚拟人
  12. 自娱自乐的FreeRTOS ——简介
  13. android开发整人软件,趣味整人软件:让手机屏幕一点就碎
  14. ArcGIS插件 - 易至天工影像加载插件
  15. Grounding DINO-开集目标检测论文解读
  16. isis宣告网络_ISIS知识点总结
  17. 好用强大优秀的杀毒软件 ESET Internet Security
  18. r语言中残差与回归值的残差图_R语言-如何处理回归中的异常值点
  19. 大一python实验二答案_大学慕课2020年用Python玩转数据题目答案
  20. java jstack使用_JAVA语言之JVM 中jstack命令使用详解

热门文章

  1. html标签缺省(自带)样式大全
  2. mysql按月进行表分区
  3. Linux 2.6 完全公平调度算法CFS(Completely Fair Scheduler) 分析
  4. git - svn 平滑到 git
  5. 技术总监谈好的程序员如何写代码
  6. 移动应用ios和网页应用_如何在iOS上一次移动多个应用
  7. Oracle 12c应用连接VIP轮训负载均衡?
  8. WCF分布式开发常见错误(25):The certificate 'CN=WCFHTTPS' must have a private key
  9. mvc 返回一个对象 到视图接收
  10. 这一新的可视化方法教你优雅地探索相关性