• Application_Error not firing when customerrors = "On"


    Application_Error not firing when customerrors = "On"

    问题

    I have code in the global.asax file's Application_Error event which executes when an error occurs and emails details of the error to myself.

    void Application_Error(object sender, EventArgs e)
    {
        var error = Server.GetLastError();
    
        if (error.Message != "Not Found")
        {
            // Send email here...
        }
    
    }

    This works fine when I'm running it in Visual Studio, however when I publish to our live server the Application_Error event does not fire.

    After some testing I can get the Application_Error firing when I set customErrors="Off", however setting it back to customErrors="On" stops the event from firing again.

    Can anyone suggest why Application_Error would not be firing when customErrors are enabled in the web.config?

    回答1

    UPDATE
    Since this answer does provide a solution, I will not edit it, but I have found a much cleaner way of solving this problem. See my other answer for details...

    Original Answer:
    I figured out why the Application_Error() method is not being invoked...

    Global.asax.cs

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute()); // this line is the culprit
        }
    ...
    }

    By default (when a new project is generated), an MVC application has some logic in the Global.asax.cs file. This logic is used for mapping routes and registering filters. By default, it only registers one filter: a HandleErrorAttribute filter. When customErrors are on (or through remote requests when it is set to RemoteOnly), the HandleErrorAttribute tells MVC to look for an Error view and it never calls the Application_Error() method. I couldn't find documentation of this but it is explained in this answer on programmers.stackexchange.com.

    To get the ApplicationError() method called for every unhandled exception, simple remove the line which registers the HandleErrorAttribute filter.

    Now the problem is: How to configure the customErrors to get what you want...

    The customErrors section defaults to redirectMode="ResponseRedirect". You can specify the defaultRedirect attribute to be a MVC route too. I created an ErrorController which was very simple and changed my web.config to look like this...

    web.config

    <customErrors mode="RemoteOnly" redirectMode="ResponseRedirect" defaultRedirect="~/Error">
      <error statusCode="404" redirect="~/Error/PageNotFound" />
    </customErrors>

    The problem with this solution is that it does a 302 redirect to your error URLs and then those pages respond with a 200 status code. This leads to Google indexing the error pages which is bad. It also isn't very conformant to the HTTP spec. What I wanted to do was not redirect, and overrite the original response with my custom error views.

    I tried to change redirectMode="ResponseRewrite". Unfortunately, this option does not support MVC routes, only static HTML pages or ASPX. I tried to use an static HTML page at first but the response code was still 200 but, at least it didn't redirect. I then got an idea from this answer...

    I decided to give up on MVC for error handling. I created an Error.aspx and a PageNotFound.aspx. These pages were very simple but they had one piece of magic...

    <script type="text/C#" runat="server">
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            Response.StatusCode = (int) System.Net.HttpStatusCode.InternalServerError;
        }
    </script>

    This block tells the page to be served with the correct status code. Of course, on the PageNotFound.aspx page, I used HttpStatusCode.NotFound instead. I changed my web.config to look like this...

    <customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="~/Error.aspx">
      <error statusCode="404" redirect="~/PageNotFound.aspx" />
    </customErrors>

    It all worked perfectly!

    Summary:

    • Remove the line: filters.Add(new HandleErrorAttribute());
    • Use Application_Error() method to log exceptions
    • Use customErrors with a ResponseRewrite, pointing at ASPX pages
    • Make the ASPX pages responsible for their own response status codes

    There are a couple downsides I have noticed with this solution.

    • The ASPX pages can't share any markup with Razor templates, I had to rewrite our website's standard header and footer markup for a consistent look and feel.
    • The *.aspx pages can be accessed directly by hitting their URLs

    There are work-arounds for these problems but I wasn't concerned enough by them to do any extra work.

    I hope this helps everyone!

    回答2

    I solved this by creating an ExceptionFilter and logging the error there instead of Application_Error. All you need to do is add a call to in in RegisterGlobalFilters

    log4netExceptionFilter.cs

    using System
    using System.Web.Mvc;
    
    public class log4netExceptionFilter : IExceptionFilter
    {
        public void OnException(ExceptionContext context)
        {
            Exception ex = context.Exception;
            if (!(ex is HttpException)) //ignore "file not found"
            {
                //Log error here
            }
        }
    }

    Global.asax.cs

    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new log4netExceptionFilter()); //must be before HandleErrorAttribute
        filters.Add(new HandleErrorAttribute());
    }
  • 相关阅读:
    AS2介绍
    .net 资源大收藏
    智能客户端(SmartClient)(转载)
    [WPF Bug清单]之(3)——暗中创建文件的打开文件对话框
    实例分析SharpDevelop代码完成功能
    [WPF Bug清单](序)与之(1)——可以多选的单选ListBox
    实例分析SharpDevelop代码完成功能(续)——添加对Boo语言的支持
    [WPF Bug清单]之(2)——RadioButton的IsChecked绑定失效
    让WPF窗体程序支持命令行方式运行的三种方式
    基于文法分析的表达式计算器的实现
  • 原文地址:https://www.cnblogs.com/chucklu/p/16170246.html
Copyright © 2020-2023  润新知