And*_*w S 7 c# exception-handling asp.net-core-mvc asp.net-core asp.net-core-middleware
我是中间件概念的新手,我目前正在努力处理我的MVC Core项目中的异常.
我想要发生的是捕获,记录异常,然后将用户发送到带有消息的友好错误页面.起初,我试图在中间件中管理所有这些,但意识到我可能没有正确地做到这一点.
因此,如果我希望这个流程发生,我应该使用我的异常日志记录中间件和app.UseExceptionHandler("/ Error"),以便中间件重新抛出异常到页面?如果是这样,我如何在错误页面中获取异常详细信息?我想先截取的异常处理机制应该是Configure中的最后一个,这是正确的吗?
我发现的所有示例都严格处理HTTP状态代码错误,如404; 我正在寻找处理实际的异常(及其子类).这样,在我的View页面中,我可以在适用的情况下抛出自己的异常(例如,如果为必填字段提供了一个null.)
Startup.cs片段:
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
Run Code Online (Sandbox Code Playgroud)
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.")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Nko*_*osi 10
我是否应该同时使用我的异常日志记录中间件和
app.UseExceptionHandler("/Error")中间件重新抛出异常到页面?
是.
仅使用您的示例的片段.
public async Task Invoke(HttpContext context) {
try {
await _next(context);
} catch (Exception ex) {
HandleException(ex);
// re -throw the original exception
// after logging the information
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
以上内容将在记录之后重新抛出原始错误,以便管道中的其他处理程序将捕获它并执行开箱即用的处理.
如何在错误页面中获取异常详细信息?
使用IExceptionHandlerPathFeature来获取异常,路径
public IActionResult Error()
{
// Get the details of the exception that occurred
var exceptionFeature = HttpContext.Features.Get<IExceptionHandlerPathFeature>();
if (exceptionFeature != null)
{
// Get which route the exception occurred at
string routeWhereExceptionOccurred = exceptionFeature.Path;
// Get the exception that occurred
Exception exceptionThatOccurred = exceptionFeature.Error;
// TODO: Do something with the exception
// Log it with Serilog?
// Send an e-mail, text, fax, or carrier pidgeon? Maybe all of the above?
// Whatever you do, be careful to catch any exceptions, otherwise you'll end up with a blank page and throwing a 500
}
return View();
}
Run Code Online (Sandbox Code Playgroud)
使用IExceptionHandlerPathFeature在ASP.NET Core中添加全局错误处理和日志记录的源代码
在上面的例子中,他们提到在视图中进行日志记录,但是你已经在自定义处理程序中完成了.
在渲染错误视图时要特别注意这个小注释.
无论你做什么,都要小心抓住任何例外情况,否则你最终会得到一个空白页并投掷500
通过插入管道,您可以避免重新发明框架已经提供的功能,并且还可以管理跨领域的问题.
| 归档时间: |
|
| 查看次数: |
5000 次 |
| 最近记录: |