【发布时间】:2017-12-01 03:39:18
【问题描述】:
我是中间件概念的新手,目前正在努力寻找在我的 MVC Core 项目中处理异常的正确方法。
我想要发生的是捕获、记录异常,然后将用户发送到带有消息的友好错误页面。起初,我试图在中间件中管理所有这些,但意识到我可能做得不对。
所以如果我希望这个流程发生,我是否应该同时使用我的异常记录中间件和 app.UseExceptionHandler("/Error") 以便中间件将异常重新抛出到页面?如果是这样,我如何在错误页面中获取异常详细信息?我想先拦截的异常处理机制应该是Configure中的最后一个是否正确?
我发现的所有示例都严格处理 HTTP 状态码错误,例如 404;我正在寻找处理实际异常(及其子类)。这样,在我的视图页面中,我可以在适用的情况下抛出我自己的异常(例如,如果视图为必填字段提供了 null。)
Startup.cs sn-p:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory, LoanDbContext context) {
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseStatusCodePages();
if (env.IsDevelopment() || env.IsEnvironment("qa")) {
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
} else {
app.UseExceptionHandler("/Error");
}
app.UseMiddleware<MyExceptionHandler>(loggerFactory);
// ... rest of Configure is irrelevant to this issue
MyExceptionHandler.cs
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Data.SqlClient;
using System.Threading.Tasks;
namespace MyCompany.MyProject.Helpers
{
/// <summary>
/// A custom Exception Handler Middleware which can be re-used in other projects.
/// </summary>
public sealed class MyExceptionHandler
{
private readonly RequestDelegate _next;
private readonly ILogger _logger;
public MyExceptionHandler(RequestDelegate next, ILoggerFactory loggerFactory) {
_next = next;
_logger = loggerFactory.CreateLogger<MyExceptionHandler>();
}
public async Task Invoke(HttpContext context) {
try {
await _next(context);
} catch (Exception ex) {
HandleException(ex);
}
}
// I realize this function looks pointless, but it will have more meat to it eventually.
public void HandleException(Exception ex) {
if (ex is ArgumentException argEx) {
_logger.LogError(0, argEx, argEx.Message);
} else if (ex is InvalidOperationException ioEx) {
_logger.LogError(0, ioEx, "An Invalid Operation Exception occurred. This is usually caused by a database call that expects "
+ "one result, but receives none or more than one.");
} else if (ex is SqlException sqlEx) {
_logger.LogError(0, sqlEx, $"A SQL database exception occurred. Error Number {sqlEx.Number}");
} else if (ex is NullReferenceException nullEx) {
_logger.LogError(0, nullEx, $"A Null Reference Exception occurred. Source: {nullEx.Source}.");
} else if (ex is DbUpdateConcurrencyException dbEx) {
_logger.LogError(0, dbEx, "A database error occurred while trying to update your item. This is usually due to someone else modifying the item since you loaded it.");
} else {
_logger.LogError(0, ex, "An unhandled exception has occurred.")
}
}
}
}
【问题讨论】:
-
只是要求好的措施。你查过官方文档docs.microsoft.com/en-us/aspnet/core/fundamentals/…
-
还有一篇好文章scottsauber.com/2017/04/03/…
-
是的,他们提供了一个 sn-p 代码“这是您使用 /Error 页面的方式”。结束。如果您的错误页面只是“嘿,发生了一些糟糕的事情!”,那就太好了。没有定制。他们说“在这里处理你的错误”,但没有说明如何获取异常。它在响应中吗?查看包?我不确定接下来的步骤。不过,第二个链接更有用。是否不担心会发生阻止呈现错误视图的异常?
-
看这篇文章的自定义错误中间件。 dusted.codes/error-handling-in-aspnet-core
-
是的,他们特别提到了在处理时尝试处理视图错误,然后使用自定义处理程序,因为它将停止渲染。
标签: c# exception-handling asp.net-core asp.net-core-mvc asp.net-core-middleware