Error Handling in ASP.NET Core

前言

 在程序中,经常需要处理比如 404500 ,502等错误,如果直接返回错误的调用堆栈的具体信息,显然大部分的用户看到是一脸懵逼的,你应该需要给用户返回那些看得懂的界面。比如,“当前页面不存在了” 等等,本篇文章主要来讲讲.NET-Core 中异常处理,以及如何自定义异常显示界面?,还有 如何定义自己的异常处理中间件?。

.NET-Core 中的异常处理

 让我们从下面这段代码讲起,写过.Net-Core 的应该不陌生,在 Startup 的 Configure 中定义异常处理的中间件。

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

  上面两种情况分别是一个是使用自带的异常处理,另外一个是将错误异常的处理,进行自己处理。两种情况如下所示:

我在HomeController 中定义了一个Test Action如下所示(仅仅为了演示,并无实际意义)

//Controllerpublic string Test(int id){    if(id == 1){        return new System.NullReferenceException("It's not equals to 1, robert!");}  return "Bingo,Robert!";
}//Routingroutes.MapRoute(name: "Error",  template: "error/",defaults: new { controller = "Home", action = "error" }
);

 使用 localhost:{port}/home/test/2 的结果像下面这样

对我localhost:{port}/home/test/1 这样呢,在不同环境下是不一样的,具体如下所示:

  • UseDeveloperException 


  • UseExceptionHandler 


这些呢,就是比较平常的 .NET-Core 的处理方式。但是看不见StatusCode,发现没有,除了自定义的时候,默认时是不提供Status Code 的。这时候,就可以用到这个

UseStatusCodePages() 想要看源码的在这 StatusCodePagesExtension Source Code。

效果怎么样的呢?如下所示:

 这是默认的处理方式,看了源码我们知道,UseStatusCodePages 有4个重载。还可以自己定义,是不是感觉比前面的高级点,下面是自定义:具体就不演示了。

app.UseStatusCodePages(async context =>{context.HttpContext.Response.ContentType = "text/plain";  await context.HttpContext.Response.WriteAsync($"What's the statusCode you got is {context.HttpContext.Response.StatusCode}");
});app.UseStatusCodePages("text/plain","What's the statusCode you got is {0}");

 截止到上面为止,基本的异常处理其实已经介绍的差不多了。但是,总感觉那么普遍呢,好像还不够特殊,并且还满足不了我们的需求,我们想要自定义错误的处理方式。比如我们想要遇到 404 时就显示 404 界面。

定义异常处理中间件

 其实上面的自定义自己的异常处理时,其实已经可以做到我们需要的情况了。我们在Error Action 中对HttpContext.Response.StatusCode 进行判断,根据不同的StatusCode return 不同的View就可以了。但是为什么我们还需要定义特定处理的中间件,主要目的是为了其他项目服务的,如果你只有一个项目,一个站点,其实并没什么必要。但是如果有很多子站点时,还是需要考虑的一下的。

 模仿了一下 UseStatusCodePagesWithReExecute这个,写了一个

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Builder;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
namespace MiddlewareDemo.CustomMiddleware{  
 /// <summary>/// Adds a StatusCodePages middleware to the pipeline. Specifies that the response body should be generated by /// re-executing the request pipeline using an alternate path. This path may contain a '{0}' placeholder of the status code./// </summary>/// <param name="app"></param>/// <param name="pathFormat"></param> //因为直接 处理404 所以就不给参数啦。/// <param name="queryFormat"></param>/// <returns></returns>public static class ErrorHandlerMiddlewareExtension{    
    public static IApplicationBuilder UseErrorHandler(            this IApplicationBuilder app,                    string pathFormat = "/error",            string queryFormat = null)        {      
          if (app == null){              
            throw new ArgumentNullException(nameof(app));}          
            return app.UseStatusCodePages(async context =>{              
              if (context.HttpContext.Response.StatusCode == StatusCodes.Status404NotFound){                
                 var newPath = new PathString(                        string.Format(CultureInfo.InvariantCulture, pathFormat, context.HttpContext.Response.StatusCode));                    var formatedQueryString = queryFormat == null ? null :                        string.Format(CultureInfo.InvariantCulture, queryFormat, context.HttpContext.Response.StatusCode);                  
                  var newQueryString = queryFormat == null ? QueryString.Empty : new QueryString(formatedQueryString);                  
                   var originalPath = context.HttpContext.Request.Path;              
                    var originalQueryString = context.HttpContext.Request.QueryString;                    // Store the original paths so the app can check it.context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(new StatusCodeReExecuteFeature(){OriginalPathBase = context.HttpContext.Request.PathBase.Value,OriginalPath = originalPath.Value,OriginalQueryString = originalQueryString.HasValue ? originalQueryString.Value : null,});context.HttpContext.Request.Path = newPath;context.HttpContext.Request.QueryString = newQueryString;                
                    try{                  
                         await context.Next(context.HttpContext);}                
                    finally{context.HttpContext.Request.QueryString = originalQueryString;context.HttpContext.Request.Path = originalPath;context.HttpContext.Features.Set<IStatusCodeReExecuteFeature>(null);}}});}} }

这样就会只处理404啦。

如下所示 :

最后分享一个 Re-execute vs Redirect 的一位大神的分析

  其实在 StatusCodePagesExtensions中还有两个方法,这两个方法也会比较实用,主要是用来当遇到异常,给你跳转到其他界面的。

//使用的话就像下面这样就可以啦app.UseStatusCodePagesWithReExecute("/error","?StatusCode={0}");app.UseStatusCodePagesWithRedirects("/error");//具体可以用哪些参数呢,可以去看源码,这里就不多介绍了。

这两个的虽然都可以得到我们想要的结果,但是过程差的有点多。先盗一下大神的两张图:

第一张是 Redirect的 :


下面一张是 ReExecute` 的

区别呢,我用Chrome Developer Console 来给你们展示一下,你们就明白啦。

这个是 redirect 的 ,很神奇吧,它返回的是200 ok. 由于是 redirect 所以 地址 redirect 到了 localhost:52298/error 。看Network可知,进行了两次请求,第一次,http://localhost:52298/home/testpage 时 返回302 Found. 我们知道这个是 404 的状态码,被 middleware “抓到”后,于是,我们再次发起请求, http://localhost:52298/error这个请求当然返回的状态码是 200 啦。所以我们在下图的结果中可以看见。200 OK。

302 : The 302 (Found) status code is used where the redirection is temporary or generally subject to change, such that the client shouldn't store and reuse the redirect URL in the future

下面的是ReExecute 的

结语

  如有陈述的不正确处,请多多评论指正。

文章推荐及参考链接

  • Use statusCodeWithReExecute and pic reference

  • StatusCodePagesExtensions Source Code

相关文章: 

  • .NET Core 2.0 正式发布信息汇总

  • .NET Standard 2.0 特性介绍和使用指南

  • .NET Core 2.0 的dll实时更新、https、依赖包变更问题及解决

  • .NET Core 2.0 特性介绍和使用指南

  • Entity Framework Core 2.0 新特性

  • 体验 PHP under .NET Core

  • .NET Core 2.0使用NLog

  • 升级项目到.NET Core 2.0,在Linux上安装Docker,并成功部署

  • 解决Visual Studio For Mac Restore失败的问题

  • ASP.NET Core 2.0 特性介绍和使用指南

  • .Net Core下通过Proxy 模式 使用 WCF

  • .NET Core 2.0 开源Office组件 NPOI

  • ASP.NET Core - Razor页面之Handlers处理方法

  • ASP.NET Core Razor页面 vs MVC

  • Razor Page–Asp.Net Core 2.0新功能  Razor Page介绍

  • ASP.Net Core 2.0中的Razor Page不是WebForm

原文地址:http://www.cnblogs.com/xiyin/p/7507405.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于python的selenium

一.安装 安装WebDriver 查看chrome版本号&#xff0c;设置-帮助-关于Google chrome&#xff0c;找到版本号。 可以到这个网站进行下载对应版本的chromedriver,如果chrome浏览器版本过高,可以下载最新版的chromedriver进行使用 Chrome for Testing availability 下载下来之后…

多信息登录、检测用户信息是否完善且引导补全

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注&#xff1a;穆雄雄的博客 前言 现在是2022年4月28日13:41:29&#xff01; 今天分享两块内容。 1.需求&#xff1a;用户可以通过手机号、邮箱来注册我们的系统&#xff0c;用户完成之后&#xff0c;可以去完善自己的个人信息…

Ch4302-IntervalGCD【线段树,树状数组,GCD】

正题 题目链接:http://contest-hunter.org:83/contest/0x40%E3%80%8C%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E8%BF%9B%E9%98%B6%E3%80%8D%E4%BE%8B%E9%A2%98/4302%20Interval%20GCD 题目大意 要求支持区间修改和区间求gcd。 解题思路 如果直接线段树gcd的话&#xff0c;区间…

PNG 图片压缩原理解析

转载自 PNG 图片压缩原理解析 什么是PNG PNG的全称叫便携式网络图型&#xff08;Portable Network Graphics&#xff09;是目前最流行的网络传输和展示的图片格式&#xff0c;原因有如下几点&#xff1a; 无损压缩&#xff1a;PNG图片采取了基于LZ77派生算法对文件进行压缩&…

element ui实现多层级复杂表单的操作(添加与回显)之表单操作交互操作

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月3日11:47:15&#xff01;劳动节假期已经过去了三天了&#xff0c;今天是被封家里的第7天&#xff0c;也是解封的第一天。 说实话&#xff0c;在家里的工作效率一点都…

POJ2182-Lost Cows【树状数组,二分】

正题 题目链接:http://poj.org/problem?id2182 题目大意 给出每头牛前面有多少个比它高的&#xff0c;求每头牛的最大高度。 解题思路 建立一个01序列&#xff0c;表示每个高度是否被占用过&#xff0c;然后倒序扫描每次找到一个没有被占用的第Ai1个位置&#xff0c;然后标…

TypeScript 2.5 发布,增加语言级重构

在 TypeScript 2.5 版本中&#xff0c;Microsoft 专注于提高开发人员的生产力&#xff0c;其范围已经超出了代码编辑器所提供的常见功能。 习惯于类型语言&#xff08;如 C&#xff03;&#xff09;的开发人员喜欢使用那些可以轻松执行常见重构的工具。现在 TypeScript 可以利…

永远不要在 MySQL 中使用 UTF-8

转载自 永远不要在 MySQL 中使用 UTF-8 最近我遇到了一个 bug&#xff0c;我试着通过 Rails 在以“utf8”编码的 MariaDB 中保存一个 UTF-8 字符串&#xff0c;然后出现了一个离奇的错误&#xff1a; Incorrect string value: ‘\xF0\x9F\x98\x83 <…’ for column ‘sum…

element ui实现多层级复杂表单的操作(添加与回显)之添加功能实现

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月3日13:35:15&#xff01;文接上篇。[element ui实现多层级复杂表单的操作&#xff08;添加与回显&#xff09;之表单操作交互操作](element ui实现多层级复杂表单的操…

POJ1151-Atlantis【线段树,扫描线,离散化】

正题 题目链接:http://poj.org/problem?id1151 题目大意 有n个矩形&#xff0c;求所以矩形的覆盖面积。 解题思路 我们用离散化一个坐标&#xff0c;然后每次用线段树维护这个宽度内覆盖高度和&#xff0c;然后定义左上的点是加入&#xff0c;右下的点是弹出。 code #incl…

Entity Framework Core Like 查询揭秘

在Entity Framework Core 2.0中增加一个很酷的功能&#xff1a;EF.Functions.Like()&#xff0c;最终解析为SQL中的Like语句&#xff0c;以便于在 LINQ 查询中直接调用。 不过Entity Framework 中默认提供了StartsWith、Contains和EndsWith方法用于解决模糊查询&#xff0c;那…

JVM发生OOM的 8 种原因、及解决办法

转载自 JVM发生OOM的 8 种原因、及解决办法 1、Java 堆空间 发生频率&#xff1a;5颗星 造成原因 无法在 Java 堆中分配对象 吞吐量增加 应用程序无意中保存了对象引用&#xff0c;对象无法被 GC 回收 应用程序过度使用 finalizer。finalizer 对象不能被 GC 立刻回收。fina…

element ui实现多层级复杂表单的操作(添加与回显)之回显功能实现

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月3日17:02:30&#xff01;文接上两篇。 [element ui实现多层级复杂表单的操作&#xff08;添加与回显&#xff09;之表单操作交互操作](element ui实现多层级复杂表单…

在Mac的Docker中运行DotNetCore2.0

最近学习Angular4&#xff0c;服务端准备使用DotNetCore API来实现&#xff0c;本文简单介绍下在Mac中怎样将DotNetCore程序部署在Docker中&#xff0c;并使用Nginx做反向代理让程序可以跑起来。 具体步骤如下 安装Docker拉取DotNetCore镜像使用VS For Mac创建DotNetCore应用…

POJ2482-Stars in Your Window【线段树,扫描线,离散化】

正题 题目链接:http://poj.org/problem?id2482 题目大意 有若干个点&#xff0c;每个点有不同的权值&#xff0c;求用一个h*w的矩阵扩起来的权值最大。 解题思路 先离散化一个坐标&#xff0c;然后另一个坐标就在x∼xw−1x∼xw−1这个区域加上权值&#xff0c;然后每个点的…

20个高级Java面试题汇总

转载自 20个高级Java面试题汇总 译文链接&#xff1a;http://www.codeceo.com/article/20-java-advanced-interview-questions.html 英文原文&#xff1a;Advanced Java Interview Questions 翻译作者&#xff1a;码农网 – 小峰 这是一个高级Java面试系列题中的部分。这一部分…

springboot实现复杂业务下的更新操作

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月4日19:25:55&#xff01;今天写了个这样的功能&#xff1a; 某用户在一天内有多个训练项目&#xff0c;比如&#xff1a;晨跑&#xff0c;有氧训练&#xff0c;跳绳这…

HDOJ5542-The Battle of Chibi【树状数组,dp】

正题 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid5542 题目大意 求序列A有多少个长度为M的递增子序列。 解题思路 用fi,jfi,j表示长度为i&#xff0c;以AjAj结尾的序列的个数。然后显然得出动态转移方程通过上一次从任意一个地方转移&#xff0c;动态转移方程&…

ASP.NET Core中为指定类添加WebApi服务功能

POCO Controller是 ASP.NET Core 中的一个特性&#xff0c;虽然在2015年刚发布的时候就有这个特性了&#xff0c;可是大多数开发者都只是按原有的方式去写&#xff0c;而没有用到这个特性。其实&#xff0c;如果利用这个特性进行稍微封装后&#xff0c;用在SOA架构中Service层的…

elementui解决el-dialog不清空内容的问题,el-dialog关闭时销毁子组件

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂 前言 现在是2022年5月5日22:48:21&#xff01; 今天在使用element-ui中的el-dialog的时候遇到了个这样的问题&#xff1a;页面上点击添加的按钮&#xff0c;弹出el-dialog对话框&#xff…