简体   繁体   English

错误处理和try / catch块与异步方法

[英]Error handling and try/catch blocks with asynchronous methods

I'm writing an ASP.Net Core 2 MVC application in Visual Studio 2017 Community Edition. 我正在Visual Studio 2017社区版中编写ASP.Net Core 2 MVC应用程序。 I'm having trouble understanding how try-catch blocks behave when dealing with asynchronous methods. 我在理解处理异步方法时try-catch块的行为时遇到麻烦。 Below are two snippets, an action in a controller and the method being called by the action. 以下是两个片段,一个是控制器中的动作,另一个是该动作所调用的方法。

Let me start by saying that the program works as intended. 首先,我要说该程序按预期工作。 The problem is that when I deliberately create an error I would expect the middleware to display the predetermined Error page. 问题是当我故意创建错误时,我希望中间件显示预定的“错误”页面。 This also works as intended in a synchronous version of the same code. 这也可以在相同代码的同步版本中按预期工作。

With this asynchronous version instead, the browser does not return any error, not even an HTTP500 Internal Server error page, it just keeps waiting for something to happen. 使用此异步版本,浏览器不会返回任何错误,甚至不会返回HTTP500 Internal Server错误页面,它只会一直等待发生某些事情。 If I then look at the WebServer Output, I see the that the exception was thrown and I even read that the error page view is run, when in fact it wasn't. 如果再查看WebServer输出,我会看到引发了异常,甚至还读取了错误页面视图正在运行的事实,而实际上并非如此。

Would someone be kind enough to explain what I'm missing here? 有人会好心地解释我在这里缺少什么吗? Thank you! 谢谢!

This is the action. 这是行动。 I skipped a lot of content in the method because it should be irrelevant and it is really long. 我跳过了方法中的很多内容,因为它应该无关紧要,而且确实很长。 Also, I don't think it is relevant, but then what do I know... so pls note that this action returns a partial view. 另外,我不认为这是相关的,但是那我知道什么...因此请注意,此操作将返回部分视图。 The action itself is called by an ajax request in another action. 该动作本身由另一个动作中的ajax请求调用。

     // Variance Report -- POST
     [HttpPost]
     [Authorize]
     [ValidateAntiForgeryToken]
     public async Task<IActionResult> Variance(VarianceModel model)
     {
         try
         {
             // Get the report data
             var varianceReport = await _report.GetVarianceReportAsync(model);

             // String that will display the current selection
             ViewBag.Parameters = model.parameterDescription;

             // Return the partial view
             return PartialView("_VariancePartial", varianceReport);
         }
         catch (Exception)
         {
             throw;
         }
     }

Here is the method being called: 这是被调用的方法:

     // REPORT
     public async Task<VarianceModel> GetVarianceReportAsync(VarianceModel model)
     {
         try
         { 
             // Do a lot of stuff here... then I deliberately try to
             // divide by zero so as to get an error:
                         try
                         {
                             VariancePercent = (VarianceValue / 0)
                         }
                         catch (Exception)
                         {
                             throw;
                         }
             // Do more stuff here as well...
                 }
             return model;
         }
         catch (Exception)
         {
             throw;
         }
     }

and finally, this is the output from the webserver: 最后,这是网络服务器的输出:

[...bla bla bla...]
WebApp> fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[0]
WebApp>       An unhandled exception has occurred: Attempted to divide by zero.
WebApp> System.DivideByZeroException: Attempted to divide by zero.
[...bla bla bla...]
WebApp> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
WebApp>       Executing action method WebApp.Controllers.HomeController.Error ( WebApp) with arguments ((null)) - ModelState is Valid
WebApp> info: 
Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ViewResultExecutor[1]
WebApp>       Executing ViewResult, running view at path /Views/Shared/Error.cshtml.
WebApp> info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
WebApp>       Executed action WebApp.Controllers.HomeController.Error (WebApp) in 1.8921ms
WebApp> info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
WebApp>       Request finished in 66679.065ms 500 text/html; charset=utf-8

You're tossing an exception but the page doesn't have a way to surface it. 您正在抛出一个异常,但是该页面没有办法显示它。 Rather than just throwing the exception, you should return an actual HTTP response: 您不仅应该抛出异常,还应该返回实际的HTTP响应:

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Variance(VarianceModel model)
{
    try
    {
        // Get the report data
        var varianceReport = await _report.GetVarianceReportAsync(model);

        // String that will display the current selection
        ViewBag.Parameters = model.parameterDescription;

        // Return the partial view
        return PartialView("_VariancePartial", varianceReport);
    }
    catch (Exception ex)
    {
        return new ObjectResult(ex);
    }
}

// REPORT
public async Task<VarianceModel> GetVarianceReportAsync(VarianceModel model)
{
    try
    {
        // divide by zero so as to get an error:
        VariancePercent = (VarianceValue / 0);
        return model;
    }
    catch (Exception)
    {
        throw;
    }
}

This won't be a very clean response however. 但是,这不是一个很干净的响应。 Ideally, you should create a partial view for the error state and return that: 理想情况下,您应该为错误状态创建局部视图并返回:

public async Task<IActionResult> Variance(VarianceModel model)
{
    try
    {
        // Get the report data
        var varianceReport = await _report.GetVarianceReportAsync(model);

        // String that will display the current selection
        ViewBag.Parameters = model.parameterDescription;

        // Return the partial view
        return PartialView("_VariancePartial", varianceReport);
    }
    catch (Exception ex)
    {
        return PartialView("_ErrorPartial", ex);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM