我正在构建一个Asp.Net Core2.2剃刀页面应用程序。我正在编写一个全局异常处理程序,以避免在许多地方使用try catch块。我关注了那篇文章-- Exception Handling Reference
这是我的代码,
在Startup.cs中
if(env.IsDevelopment())
{
//app.UseDeveloperExceptionPage(new DeveloperExceptionPageOptions {
// SourceCodeLineCount = 2
//});
//app.UseDatabaseErrorPage();
app.UseExceptionHandler("/Error");
app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseExceptionMiddleware();
} else {...}
在ExceptionMiddleware.cs中
public ExceptionMiddleware(RequestDelegate next,IMailService emailSender)
{
_next = next;
_emailSender = emailSender;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
} catch(Exception ex)
{
EmailException(context,ex);
}
}
private async void EmailException(HttpContext context,Exception ex)
{
var uaString = context.Request.Headers["User-Agent"].ToString();
var ipAnonymizedString = context.Connection.RemoteIpAddress.AnonymizeIP();
var userId = "Unknown";
var profileId = "Unknown";
if(context.User.Identity.IsAuthenticated)
{
userId = context.User.FindFirstValue(ClaimTypes.NameIdentifier);
profileId = context.User.GetUserClaim(ClaimsKey.ProfileId);
}
var sb = new StringBuilder($"An error has occurred on {context.Request.Host}. \r\n \r\n");
sb.Append($"Path = {context.Request.Path} \r\n \r\n");
sb.Append($"Error Message = {ex.Message} \r\n");
sb.Append($"Error Source = {ex.Source} - {profileId} \r\n");
if(ex.InnerException != null)
{
sb.Append($"Inner Exception = {ex.InnerException.ToString()} \r\n");
} else
{
sb.Append("Inner Exception = null \r\n");
}
sb.Append($"Error StackTrace = {ex.StackTrace} \r\n");
await _emailSender.SendMasterEmailAsync($"Error on {context.Request.Host}.",sb.ToString(),uaString,ipAnonymizedString,userId);
throw ex;
}
现在,我正在我的一个页面get请求中创建一个异常,如下所示,
public void OnGet()
{
throw new Exception();
}
中间件捕获异常,并在发送电子邮件后抛出该异常。然后,Visual Studio显示应用程序处于中断模式,并且visual studio停止。但是在应用程序中断和停止之前,我的Error.cshtml.cs没有捕获到异常。你知道我哪里错了吗?
发布于 2019-06-23 22:58:01
在他的async guidance GitHub存储库中,David Fowler指出:
在ASP.NET核心应用程序中使用async void是 bad。避免它,永远不要做它。通常,当开发人员试图实现由控制器操作触发的触发和忘记模式时,就会使用它。如果抛出异常,异步void方法将使进程崩溃。
对于您描述的错误,最后一行是至关重要的-您的应用程序抛出了一个异常,这将导致进程崩溃。
对于EmailException
,您应该从使用async void
切换到使用async Task
,如下所示:
public ExceptionMiddleware(RequestDelegate next,IMailService emailSender)
{
...
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch(Exception ex)
{
await EmailException(context, ex); // Await.
}
}
private async Task EmailException(HttpContext context, Exception ex) // Return a Task.
{
...
throw ex;
}
如果您尝试使用async void
的原因是为了在向用户返回响应之前不必等待电子邮件发送,那么您可能需要考虑使用Background Task。
https://stackoverflow.com/questions/56724429
复制相似问题