本文介绍了处理 ASP.NET Core 应用中常见错误的一些方法。
开发人员异常页
要将应用配置为显示有关异常的详细信息的页面,请使用开发人员异常页。 该页面通过 Microsoft.AspNetCore.App 元包
中的 Microsoft.AspNetCore.Diagnostics 包提供。 向 Startup.Configure
方法添加代码行:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
env.EnvironmentName = EnvironmentName.Production;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
}
将对 UseDeveloperExceptionPage
的调用放在要对其捕获异常的任何中间件(例如,app.UseMvc
)前面。
警告
仅当应用程序在开发环境中运行时才启用开发人员异常页。 否则当应用程序在生产环境中运行时,详细的异常信息会向公众泄露 了解环境配置
。
要查看开发人员异常页,请将环境设置为 Development
,运行示例应用,并向应用的基 URL 添加 ?throw=true
。 该页面包括几个选项卡,这些选项卡中包含关于异常和请求的信息。 第一个选项卡包括堆栈跟踪:
下一个选项卡显示查询字符串参数(如有):
如果请求具有 cookie,它们在“Cookie”选项卡上显示。标头出现在最后一个选项卡中:
配置自定义异常处理页
配置当应用未在 Development
环境中运行时要使用的异常处理程序页:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
env.EnvironmentName = EnvironmentName.Production;
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/error");
}
}
在 Razor Pages 应用中,dotnet new
Razor Pages 模板在 Pages 文件夹中提供“错误”页面和错误 PageModel
类。
在 MVC 应用中,不要使用 HTTP 方法特性(如 HttpGet
)修饰错误处理程序操作方法。 显式谓词可阻止某些请求访问方法。 允许匿名访问方法,以便未经身份验证的用户能够接收错误视图。
例如,以下错误处理程序方法由dotnet new
MVC 模板提供并在主控制器中显示:
[AllowAnonymous]
public IActionResult Error()
{
return View(new ErrorViewModel
{ RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
配置状态代码页
默认情况下,应用不会为 HTTP 状态代码提供丰富状态代码页,例如 404 未找到。 要提供状态代码页,请使用状态代码页中间件。
该中间件通过Microsoft.AspNetCore.App 元包
中的 Microsoft.AspNetCore.Diagnostics 包提供。
向 Startup.Configure
方法添加代码行:
app.UseStatusCodePages();
应在管道中的请求处理中间件之前调用 UseStatusCodePages
(例如,静态文件中间件和 MVC 中间件)。
默认情况下,状态代码页中间件为常见状态代码(如 404)添加纯文本处理程序:
该中间件支持多种扩展方法。 一种方法采用 Lambda 表达式:
// Expose the members of the 'Microsoft.AspNetCore.Http' namespace
// at the top of the file:
// using Microsoft.AspNetCore.Http;
app.UseStatusCodePages(async context =>
{
context.HttpContext.Response.ContentType = "text/plain";
await context.HttpContext.Response.WriteAsync(
"Status code page, status code: " +
context.HttpContext.Response.StatusCode);
});
UseStatusCodePages
重载需要使用内容类型和格式字符串:
app.UseStatusCodePages("text/plain", "Status code page, status code: {0}");
重定向重新执行扩展方法
UseStatusCodePagesWithRedirects
:
- 向客户端发送“302 - 已找到”状态代码。
- 将客户端重定向到 URL 模板中的位置。
该模板可能包括状态代码的 {0}
占位符。 模板必须以正斜杠 (/
) 开头。
app.UseStatusCodePagesWithRedirects("/error/{0}");
UseStatusCodePagesWithReExecute
:
- 向客户端返回原始状态代码。
- 指定应使用备用路径重新执行请求管道,从而生成响应正文。
该模板可能包括状态代码的 {0}
占位符。 模板必须以正斜杠 (/
) 开头。
app.UseStatusCodePagesWithReExecute("/error/{0}");
可禁用 Razor 页处理程序方法或 MVC 控制器中的特定请求的状态代码页。 要禁用状态代码页,请尝试从请求的 HttpContext.Features
集合中检索 IStatusCodePagesFeature
,并在功能可用时禁用该功能:
var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();
if (statusCodePagesFeature != null)
{
statusCodePagesFeature.Enabled = false;
}
若要在应用中使用指向终结点的 UseStatusCodePages*
重载,请为终结点创建 MVC 视图或 Razor Page。 例如,Razor Pages 应用的dotnet new
模板将生成以下页面和页面模型类:
Error.cshtml:
@page
@model ErrorModel
@{
ViewData["Title"] = "Error";
}
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@Model.RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed
information about the error that occurred.
</p>
<p>
<strong>Development environment should not be enabled in deployed applications
</strong>, as it can result in sensitive information from exceptions being
displayed to end users. For local debugging, development environment can be
enabled by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment
variable to <strong>Development</strong>, and restarting the application.
</p>
Error.cshtml.cs:
public class ErrorModel : PageModel
{
public string RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None,
NoStore = true)]
public void OnGet()
{
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
异常处理代码
异常处理页中的代码可能会引发异常。 建议在生产错误页面中包含纯静态内容。
此外还要注意,一旦发送响应的标头,则无法更改响应的状态代码,也不能运行任何异常页或处理程序。 必须完成响应或中止连接。
服务器异常处理
除应用程序中的异常处理逻辑外,托管应用程序的服务器
也会执行一些异常处理。 如果服务器在发送标头之前捕获异常,服务器将发送没有正文的 500 内部服务器错误响应。 如果服务器在已发送标头后捕获异常,服务器会关闭连接。 应用程序无法处理的请求将由服务器进行处理。 发生的任何异常都将由服务器进行处理。 任何配置的自定义错误页面或异常处理中间件或筛选器都不会影响此行为。
启动异常处理
应用程序启动期间发生的异常仅可在承载层进行处理。 利用Web
主机,你可以使用 captureStartupErrors
和 detailedErrors
键配置主机在响应启动期间出现错误时的行为方式
。
仅当捕获的启动错误发生在主机地址/端口绑定之后,承载层才会为该错误显示错误页。 如果绑定因任何原因而失败,则承载层会记录关键异常,dotnet 进程崩溃,且在Kestrel
服务器上运行应用时,不会显示任何错误页。
在 IIS
或IIS Express
上运行应用时,如果无法启动进程,ASP.NET Core 模块
将返回 502.5 进程失败。 要了解在通过 IIS 托管时如何排查启动问题,请参阅 对 IIS 上的 ASP.NET Core 进行故障排除
。 要了解如何排查 Azure 应用服务的启动问题,请参阅 对 Azure 应用服务上的 ASP.NET Core 进行故障排除
。
ASP.NET Core MVC 错误处理
MVC
应用还有一些其他的错误处理选项,例如配置异常筛选器和执行模型验证。
异常筛选器
在 MVC 应用中,异常筛选器可以进行全局配置,也可以为每个控制器或每个操作单独配置。 这些筛选器处理在执行控制器操作或其他筛选器时出现的任何未处理的异常。 不会以其他方式调用这些筛选器。 要了解详细信息,请参阅筛选器
。
[!TIP]
异常筛选器非常适用于捕获 MVC 操作内出现的异常,但灵活性不如错误处理中间件。 一般情况下最好使用中间件;仅在需要根据所选 MVC 操作以不同方式执行错误处理时,才使用筛选器。
处理模型状态错误
模型验证
在每个控制器操作被调用之前发生,操作方法负责检查 ModelState.IsValid
并相应地作出反应。
某些应用使用标准约定处理模型验证错误,在这种情况下,使用筛选器
可以更好地实施这种策略。 你需要使用无效模型状态测试操作的行为。 查看测试控制器逻辑
了解详情。