简体   繁体   English

global.asax 中的 Application_Error 未捕获 WebAPI 中的错误

[英]Application_Error in global.asax not catching errors in WebAPI

For a project I am working on, one of the things we're implementing is something that we have code for in some of my teams older ASP.NET and MVC projects - an Application_Error exception catcher that dispatches an email to the development team with the exception experience and most relevant details.对于我正在从事的项目,我们正在实施的其中一项内容是我们在我的一些团队较旧的 ASP.NET 和 MVC 项目中拥有代码的内容 - Application_Error异常捕获器,它向开发团队发送一封电子邮件,其中包含异常经验和最相关的细节。

Here's how it looks:这是它的外观:

Global.asax:全球.asax:

protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    string path = "N/A";
    if (sender is HttpApplication)
        path = ((HttpApplication) sender).Request.Url.PathAndQuery;

    string args = string.Format("<b>Path:</b> {0}", path);

    // Custom code that generates an HTML-formatted exception dump
    string message = Email.GenerateExceptionMessage(ex, args);

    // Custom code that sends an email to the dev team.
    Email.SendUnexpectedErrorMessage("Some App", message);
}

One "minor" problem, though - when I intentionally have a part of the code throw an exception in order to test this mechanism...但是,有一个“小”问题——当我故意让一部分代码抛出异常以测试这种机制时......

public static void GetMuffinsByTopping(string topping)
{
    throw new Exception("Test Exception!", new Exception("Test Inner Exception!!!"));

    // Actual repository code is unreachable while this test code is there
}

The front-end JavaScript is immediately intercepting an HTTP 500 request, but the global.asax.cs code noted above is not being reached (I set a breakpoint on the first executing line of the method.)前端 JavaScript 立即拦截了一个 HTTP 500 请求,但是没有到达上面提到的 global.asax.cs 代码(我在方法的第一行执行了一个断点。)

Question: In what way can I get the "old" Application_Error handler to dispatch error emails, so that our team's developers can more easily debug our application?问题:如何让“旧的” Application_Error处理程序发送错误电子邮件,以便我们团队的开发人员可以更轻松地调试我们的应用程序?

Abstract out your error handling logic from Application_Error into its own function.将您的错误处理逻辑从Application_Error抽象为它自己的函数。 Create a Web API exception filter .创建一个Web API 异常过滤器

//register your filter with Web API pipeline
//this belongs in the Application_Start event in Global Application Handler class (global.asax)
//or some other location that runs on startup
GlobalConfiguration.Configuration.Filters.Add(new LogExceptionFilterAttribute());

//Create filter
public class LogExceptionFilterAttribute : ExceptionFilterAttribute 
{
    public override void OnException(HttpActionExecutedContext context)
    {
        ErrorLogService.LogError(context.Exception);
    }
}

//in global.asax or global.asax.cs
protected void Application_Error(object sender, EventArgs e)
{
    Exception ex = Server.GetLastError();
    ErrorLogService.LogError(ex);
} 

//common service to be used for logging errors
public static class ErrorLogService
{
    public static void LogError(Exception ex)
    {
        //Email developers, call fire department, log to database etc.
    }
}

Errors from Web API do not trigger the Application_Error event.来自 Web API 的错误不会触发 Application_Error 事件。 But we can create an exception filter and register it to handle the errors.但是我们可以创建一个异常过滤器并注册它来处理错误。 Also see Global Error Handling in ASP.NET Web API 2 .另请参阅ASP.NET Web API 2 中的全局错误处理

In my case, i prefer not use Web.config.就我而言,我不喜欢使用 Web.config。 Then i created code above in Global.asax file:然后我在 Global.asax 文件中创建了上面的代码:

protected void Application_Error(object sender, EventArgs e)
    {
        Exception ex = Server.GetLastError();

        //Not Found (When user digit unexisting url)
        if(ex is HttpException && ((HttpException)ex).GetHttpCode() == 404)
        {
            HttpContextWrapper contextWrapper = new HttpContextWrapper(this.Context);

            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "NotFound");

            IController controller = new ErrorController();
            RequestContext requestContext = new RequestContext(contextWrapper, routeData);
            controller.Execute(requestContext);
            Response.End();
        }
        else //Unhandled Errors from aplication
        {
            ErrorLogService.LogError(ex);
            HttpContextWrapper contextWrapper = new HttpContextWrapper(this.Context);

            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "Index");

            IController controller = new ErrorController();
            RequestContext requestContext = new RequestContext(contextWrapper, routeData);
            controller.Execute(requestContext);
            Response.End();
        }
    }

And thtat is my ErrorController.cs那是我的 ErrorController.cs

public class ErrorController : Controller
{
    // GET: Error
    public ViewResult Index()
    {
        Response.StatusCode = 500;
        Exception ex = Server.GetLastError();
        return View("~/Views/Shared/SAAS/Error.cshtml", ex);
    }

    public ViewResult NotFound()
    {
        Response.StatusCode = 404;
        return View("~/Views/Shared/SAAS/NotFound.cshtml");
    }
}

And that is my ErrorLogService.cs copyed from @mason class这是我从@mason 类复制的 ErrorLogService.cs

//common service to be used for logging errors
public static class ErrorLogService
{
    public static void LogError(Exception ex)
    {
        //Do what you want here, save log in database, send email to police station
    }
}

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

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