博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[转]在ASP.NET Core使用Middleware模拟Custom Error Page功能
阅读量:6177 次
发布时间:2019-06-21

本文共 3729 字,大约阅读时间需要 12 分钟。

本文转自:

一、使用场景

  在传统的ASP.NET MVC中,我们可以使用HandleErrorAttribute特性来具体指定如何处理Action抛出的异常.只要某个Action设置了HandleErrorAttribute特性,那么默认的,当这个Action抛出了异常时MVC将会显示Error视图,该视图位于~/Views/Shared目录下。

  自定义错误页面的目的,就是为了能让程序在出现错误/异常的时候,能够有较好的显示体验。有时候在Error视图中也会发生错误,这时ASP.NET/MVC将会显示其默认的错误页面(黄底红字),为了避免这种情况的出现,我们都是在Web.config文件的customErrors节中来自定义错误页面,来启用自定义错误处理:

 

  1. <configuration>
  2. <system.web>
  3. <compilation debug="true" />
  4. <customErrors mode="On" defaultRedirect="DefaultError">
  5. <error statusCode="401" redirect="Http401Error"/>
  6. <error statusCode="403" redirect="Http403Error"/>
  7. <error statusCode="404" redirect="Http404Error"/>
  8. <error statusCode="500" redirect="Http500Error"/>
  9. </customErrors>
  10. </system.web>
  11. </configuration>

二、.NET Core实现

  既然想用ASP.NET Core中的中间件模拟Custom Error Page功能,那首先我从配置下手。大家都知道.NET Core中配置文件系统发生了很大的变化,默认都是采用Json格式的文件进行存储的,当然配置文件也可以是其它类型的,这里我们就不深入探讨了,我们就围绕Json配置文件实现好了:

  1. "ErrorPages": {
  2. "401": "/Error/Http401Page",
  3. "403": "/Error/Http403Page",
  4. "404": "/Error/Http404Page",
  5. "500": "/Error/Http500Page"
  6. }

  我们在Startup类中定义两个变量,用来存储配置文件读取出来的信息如下:

  1. public IConfigurationRoot Configuration {
    get; }
  2. internal static IDictionary<int, string> ErrorPages {
    get; } = new Dictionary<int, string>();

  配置文件中定义的ErrorPages节点,用于存储我们需要的Http状态编码并包含使用到的错误页面地址, 将他们用Startup类中的ErrorPages变量使用Key/Value的形式,读取出来。

  接下来我们要从JSON配置文件中读取信息填充到ErrorPages:

  1. var builder = new ConfigurationBuilder()
  2. .SetBasePath(env.ContentRootPath)
  3. .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
  4. .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
  5. .AddEnvironmentVariables();
  6. Configuration = builder.Build();
  7. foreach (var c in Configuration.GetSection("ErrorPages").GetChildren())
  8. {
  9. var key = Convert.ToInt32(c.Key);
  10. if (!ErrorPages.Keys.Contains(key))
  11. {
  12. ErrorPages.Add(key, c.Value);
  13. }
  14. }

  现在我们使用今天的主角,创建一个ASP.NET Core的Middleware,用于实现Custom Error Page功能:

  1. public class CustomErrorPagesMiddleware
  2. {
  3. private readonly RequestDelegate _next;
  4. private readonly ILogger _logger;
  5. public CustomErrorPagesMiddleware(ILoggerFactory loggerFactory, RequestDelegate next)
  6. {
  7. _next = next;
  8. _logger = loggerFactory.CreateLogger<CustomErrorPagesMiddleware>();
  9. }
  10. public async Task Invoke(HttpContext context)
  11. {
  12. try
  13. {
  14. await _next(context);
  15. }
  16. catch (Exception ex)
  17. {
  18. _logger.LogError(0, ex, "An unhandled exception has occurred while executing the request");
  19. if (context.Response.HasStarted)
  20. {
  21. _logger.LogWarning("The response has already started, the error page middleware will not be executed.");
  22. throw;
  23. }
  24. try
  25. {
  26. context.Response.Clear();
  27. context.Response.StatusCode = 500;
  28. return;
  29. }
  30. catch (Exception ex2)
  31. {
  32. _logger.LogError(0, ex2, "An exception was thrown attempting to display the error page.");
  33. }
  34. throw;
  35. }
  36. finally
  37. {
  38. var statusCode = context.Response.StatusCode;
  39. if (Startup.ErrorPages.Keys.Contains(statusCode))
  40. {
  41. context.Request.Path = Startup.ErrorPages[statusCode];
  42. await _next(context);
  43. }
  44. }
  45. }

  这样就完成了,从响应Response的StatusCode到配置的具体页面的跳转。

  当然我们最后,还要为这个中间件添加一个扩展方法,ASP.NET Core中为 IApplictionBuilder创建了好多的扩展方法,其实也好比它的名子一样,它就应该是一个建造者模式。

  扩展方法如下:

 

  1. public static class BuilderExtensions
  2. {
  3. public static IApplicationBuilder UseCustomErrorPages(this IApplicationBuilder app)
  4. {
  5. return app.UseMiddleware<CustomErrorPagesMiddleware>();
  6. }
  7. }

 

  最后在Startup类中的Configure方法中加入自定义错误的扩展:

  1. app.UseCustomErrorPages();

三、源代码

  如果你对文中的代码感兴趣,也可以到我的Github上去看下这个例子的源代码:

 

------------------分割线--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

  开源推广:  

  YOYOFx,一个轻量级用于构建基于 HTTP 的 Web 服务,支持.NET Framework 、.NET  CORE、 Mono 平台。

  本着学习的态度,造了这个轮子,也是为了更好的了解各个框架的原理和有点,还希望可以和大家多交流 。

  GitHub:  Star下, 欢迎一起交流。 .NET Core 和 YOYOFx 的交流群:   

 

转载地址:http://aowda.baihongyu.com/

你可能感兴趣的文章
IO与NIO
查看>>
go_wed编程笔记
查看>>
iptables防火墙的使用
查看>>
浅谈js中的继承
查看>>
软件工程 之 画扇面
查看>>
zabbix mysql数据库迁移方案
查看>>
VirtualBox虚拟机网络设置(四种方式)
查看>>
[C# 基础知识系列]专题十六:Linq介绍
查看>>
Cisco 胖瘦AP转换
查看>>
jQuery学习
查看>>
MYSQL 锁:metadata lock
查看>>
3.5 数组
查看>>
XAlign:用于代码对齐的Xcode插件
查看>>
sqlserver表分区的相关总结
查看>>
exchange 2010 专题- 个人存档
查看>>
java
查看>>
Tomcat集群Cluster实现原理
查看>>
人人都应当控制的一些电脑操作技能
查看>>
百度echarts自定义主题使用
查看>>
ASP.NET MVC3中给DropDownList添加默认选项
查看>>