ASP.NET Core 中文文档 第三章 原理(5)错误处理
原文:Error Handling
作者:Steve Smith
翻译:谢炀(Kiler)
校对:高嵩(jack2gs)、何镇汐
当你的ASP.NET应用发生错误的时候, 你可以采用本文所述的各种方法来处理这些问题。
章节:
配置错误处理页面
你在 Startup 类的 Configure() 方法中为每一个请求配置管道 (更多内容请参考 Application Startup)。 你可以轻松的添加一个仅仅适用于开发阶段的简单异常页面。只需要在项目中添加 Microsoft.AspNetCore.Diagnostics 依赖,并且添加一行代码到 Startup.cs 的 Configure() 方法里面:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseIISPlatformHandler();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
以上代码包含一个检查,以确保添加调用 UseDeveloperExceptionPage 的环境是开发环境。这是一个好的实践,因为你通常情况下并不希望在应用程序已经处于生产环境的情况下,将你的应用程序的详细异常信息对外公开. 详细了解如何配置环境。
示例应用程序包括一个创建异常的简单机制的例子:
public static void HomePage(IApplicationBuilder app)
{
app.Run(async (context) =>
{
if (context.Request.Query.ContainsKey("throw"))
{
throw new Exception("Exception triggered!");
}
var builder = new StringBuilder();
builder.AppendLine("<html><body>Hello World!");
builder.AppendLine("<ul>");
builder.AppendLine("<li><a href=\"/?throw=true\">Throw Exception</a></li>");
builder.AppendLine("<li><a href=\"/missingpage\">Missing Page</a></li>");
builder.AppendLine("</ul>");
builder.AppendLine("</body></html>");
context.Response.ContentType = "text/html";
await context.Response.WriteAsync(builder.ToString());
});
}
如果请求中包含一个变量名为 throw 的非空查询字符串 (例如,路径: /?throw=true), 那么就会抛出一个异常。如果环境被设置为 Development , 开发者异常页面将会被显示:

当不在开发模式下, 建议使用 UseExceptionHandler 方法来配置一个错误处理路径:
app.UseExceptionHandler("/Error");
使用开发者异常页面
当Web请求中发生无法捕获异常的时候,开发者异常页面会显示有用的调试信息。页面包含几个选项卡页面来显示Web请求中引发的异常信息。 第一个选项卡页面包含错误堆栈跟踪信息:

第二个选项卡页面显示查询字符串信息,如果有的话:

在这个案例里面,你可以看到 throw 参数的值被传递到了请求。这个请求不包含任何cookies,但是如果有任何cookies,他们的值会显示在cookies选项卡页面。你可以在最后一个选项卡页面查看到头信息:

配置状态码页面
在默认情况下,你的应用程序无法为Http状态码返回(例如:500 (服务器内部错误) or 404 (文件无法找到))提供一个富文本的HTTP状态码页面。你可以在 Configure 方法中加入一行 StatusCodePagesMiddleware 代码:
app.UseStatusCodePages();
在默认情况下,系统会为普通的http状态码添加一个非常简单纯文本的处理,例如,下面是404无法找到文件状态码返回的结果。

中间件提供不同的扩展方法,你也可以使用自定义lambda表达式来配置参数:
app.UseStatusCodePages(context =>
context.HttpContext.Response.SendAsync("Handler, status code: " +
context.HttpContext.Response.StatusCode, "text/plain"));
另外, 你也可以简单的传递一个内容类型和格式化字符串:
app.UseStatusCodePages("text/plain", "Response, status code: {0}");
中间件也能处理重定向请求 (无论是绝对路径还是相对路径), 把状态码作为URL的一部分进行传递:
app.UseStatusCodePagesWithRedirects("~/errors/{0}");
在上面的案例中, 客户端浏览器遇到 302 / Found状态码返回时,会重定向到指定的页面.
另外,中间件也提供设置一个新的路径字符串的方式来重新执行请求。
app.UseStatusCodePagesWithReExecute("/errors/{0}");
方法 UseStatusCodePagesWithReExecute 会返回原始的浏览器状态码页面,但是也会执行路径中指定的处理程序。
如果你需要对某些请求禁止状态码页面, 可以使用以下代码:
var statusCodePagesFeature = context.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
错误处理在CS交互模式下的限制
Web应用在错误处理功能上因为断开HTTP请求和响应的特性有些特别的限制,有的应用程序,在你设计错误处理行为时请注意以下几点。
- 一旦响应文件头发送出去以后,你就无法再修改响应的状态码了,无论是任何异常页面或处理程序都无法执行。响应必须完成或者连接中断退出。
- 如果客户端在响应中期断开,你无法把当前响应的剩余内容发送给客户端。
- 在你的错误处理层之下,总是有可能存在有例外的一层。
- 不要忘了,错误处理页面也会产生异常. 生产环境异常页面采用纯静态页面是个不错的建议。
遵从上述建议将有助于确保您的应用程序保持响应,并且能很好地处理应用程序可能发生的异常。
服务器错误处理
除了你的应用程序中的错误处理逻辑,托管应用程序的服务器也将执行一些错误处理。如果服务器在头信息发送出去之前捕获到异常,它会发出不带主体的500内部服务器错误响应。如果在头文件发送出去之后捕获到异常必须关闭连接。那些不是被你的应用程序处理的请求将被服务器处理,并且发生的任何异常将被服务器的错误处理机制来处理。任何在你的应用程序里面配置好自定义错误页、错误处理中间件、过滤器都无法影响此行为。
Startup 错误处理
处理异常最为棘手的地方是在你的应用程序启动的时候。只有承载层可以处理应用程序的启动过程中发生的异常。应用程序启动时发生的异常也会影响服务器的行为。例如,要启用SSL in Kestrel,有些必须用 KestrelServerOptions.UseHttps() 配置服务器。如果一个异常在 Startup 代码行之前发生,则默认情况下托管将捕获异常,并启动服务器,然后在非SSL端口上显示一个错误页面。如果有异常情况发生在该行执行之后, 则错误页面将通过HTTPS服务生效。
ASP.NET MVC 错误处理
异常过滤器
异常过滤器可以在 MVC 应用程序的全局范围内或者每个Controller或者每个Action上进行配置。这些过滤器会处理controller action或其他过滤器的执行过程中发生的任何未处理的异常,其他情况则不会被调用。异常过滤器更多内容请见 过滤器。
小技巧
异常过滤器捕获MVC Action中发生的异常是很好的,但他们不如错误处理中间件灵活。一般情况下尽可能使用中间件,只有当在你需要在处理异常的时候需要特别指定某些MVC action的时候,过滤器才被建议使用。
处理模型状态错误
模型验证 在每个controller action被调用之前发生,Action方法的职责是检查 ModelState.IsValid 并作出适当的交互反应。在大部分情况下,特定的交互会返回特定的错误响应,最好详细说明模型验证失败的原因。
有些应用程序会选择遵循标准惯例处理模型验证错误,在这种情况下,过滤器可以作为某些策略的实现场所。您应该测试你的Action是否与有效和无效的模型状态有关联(了解更多有关 测试controller逻辑)的行为。
ASP.NET Core 中文文档 第三章 原理(5)错误处理的更多相关文章
- ASP.NET Core 中文文档 第三章 原理(6)全球化与本地化
原文:Globalization and localization 作者:Rick Anderson.Damien Bowden.Bart Calixto.Nadeem Afana 翻译:谢炀(Kil ...
- ASP.NET Core 中文文档 第三章 原理(1)应用程序启动
原文:Application Startup 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay) ASP.NET Core 为你的应用程 ...
- ASP.NET Core 中文文档 第三章 原理(13)管理应用程序状态
原文:Managing Application State 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:高嵩 在 ASP.NET Core 中,有多种途径可以对应用程序的状态进行 ...
- ASP.NET Core 中文文档 第三章 原理(2)中间件
原文:Middleware 作者:Steve Smith.Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:许登洋(Seay) 章节: 什么是中间件 用 IApplicationBu ...
- ASP.NET Core 中文文档 第三章 原理(3)静态文件处理
原文:Working with Static Files 作者:Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay).孟帅洋(书缘) 静态文 ...
- ASP.NET Core 中文文档 第三章 原理(10)依赖注入
原文:Dependency Injection 作者:Steve Smith 翻译:刘浩杨 校对:许登洋(Seay).高嵩 ASP.NET Core 的底层设计支持和使用依赖注入.ASP.NET Co ...
- ASP.NET Core 中文文档 第三章 原理(11)在多个环境中工作
原文: Working with Multiple Environments 作者: Steve Smith 翻译: 刘浩杨 校对: 孟帅洋(书缘) ASP.NET Core 介绍了支持在多个环境中管 ...
- ASP.NET Core 中文文档 第三章 原理(17)为你的服务器选择合适版本的.NET框架
原文:Choosing the Right .NET For You on the Server 作者:Daniel Roth 翻译:王健 校对:谢炀(Kiler).何镇汐.许登洋(Seay).孟帅洋 ...
- ASP.NET Core 中文文档 第三章 原理(7)配置
原文:Configuration 作者:Steve Smith.Daniel Roth 翻译:刘怡(AlexLEWIS) 校对:孟帅洋(书缘) ASP.NET Core 支持多种配置选项.应用程序配置 ...
- ASP.NET Core 中文文档 第三章 原理(8)日志
原文:Logging 作者:Steve Smith 翻译:刘怡(AlexLEWIS) 校对:何镇汐.许登洋(Seay) ASP.NET Core 内建支持日志,也允许开发人员轻松切换为他们想用的其他日 ...
随机推荐
- JavaScript var关键字、变量的状态、异常处理、命名规范等介绍
本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...
- 120项改进:开源超级爬虫Hawk 2.0 重磅发布!
沙漠君在历时半年,修改无数bug,更新一票新功能后,在今天隆重推出最新改进的超级爬虫Hawk 2.0! 啥?你不知道Hawk干吗用的? 这是采集数据的挖掘机,网络猎杀的重狙!半年多以前,沙漠君写了一篇 ...
- android studio 使用 jni 编译 opencv 完整实例 之 图像边缘检测!从此在andrid中自由使用 图像匹配、识别、检测
目录: 1,过程感慨: 2,运行环境: 3,准备工作: 4,编译 .so 5,遇到的关键问题及其解决方法 6,实现效果截图. (原创:转载声明出处:http://www.cnblogs.com/lin ...
- javascript 判断参数类型大全
js 判断类型的在开发中是很常用的,因为js 是弱类型的语言,var 可以接受任何形式的类型,但是在真正的开发中,我们需要根据不同类型做不同的处理,所以这个是必须的精通. 首先需要知道 typeof这 ...
- [转]Patch文件结构详解
N久不来 于是不知道扔在哪儿于是放这里先 如果你觉得碍事的话 帮我扔到合适的版块去.. 导读这是一篇说明文 它介绍了标准冒险岛更新文件(*.patch;*.exe)的格式文章的最后附了一段C#的参考代 ...
- C#调用C++代码遇到的问题总结
最近在开发服务后台的时候,使用c#调用了多个c++编写的dll,期间遇到了一系列的问题,经过一番努力最后都一一解决了,在此做个总结,方便以后参考,毕竟这些问题也都是很常见的,主要有以下问题: 类型对照 ...
- 游戏AI系列内容 咋样才能做个有意思的AI呢
游戏AI系列内容 咋样才能做个有意思的AI呢 写在前面的话 怪物AI怎么才能做的比较有意思.其实这个命题有点大,我作为一个仅仅进入游戏行业两年接触怪物AI还不到一年的程序员来说,来谈这个话题,我想我是 ...
- Ubuntu搭建lnmp环境
1.安装nginx 安装 sudo apt-get install nginx 服务启动.停止.重启 /etc/init.d/nginx start /usr/sbin/nginx -c /etc/n ...
- EC笔记:第4部分:20、传递引用代替传值
考虑以下场景: #include <iostream> #include <string> using namespace std; struct Person { strin ...
- BPM助力企业数字化转型
自九十年代末,流程管理开始引入国内,至今已经有20多年的历史了,由最初的部门级应用向企业级应用转变,大家的认知也经历了一系列的发展变化.不同阶段的信息化水平对企业的流程以及BPM平台也提出了不同的需求 ...