Programing

customerrors =“On”인 경우 Application_Error가 발생하지 않습니다

crosscheck 2020. 7. 10. 08:00
반응형

customerrors =“On”인 경우 Application_Error가 발생하지 않습니다


나는 코드가 global.asax파일의 Application_Error오류가 자신에게 오류 정보를 발생 및 이메일 때 실행되는 이벤트.

void Application_Error(object sender, EventArgs e)
{
    var error = Server.GetLastError();

    if (error.Message != "Not Found")
    {
        // Send email here...
    }

}

Visual Studio에서 실행할 때 제대로 작동하지만 라이브 서버에 게시하면 Application_Error이벤트가 발생하지 않습니다.

일부 테스트 Application_Error후을 설정할 때 발사를 얻을 수 customErrors="Off"있지만 다시 설정 customErrors="On"하면 이벤트가 다시 발생하지 않습니다.

에서 활성화 된 Application_Error경우 발사하지 않을지 제안 할 수 있습니까 ?customErrorsweb.config


업데이트이
답변은 해결책을 제공하기 때문에 편집하지는 않지만이 문제를 해결하는 훨씬 깔끔한 방법을 찾았습니다. 자세한 내용은 다른 답변 을 참조하십시오 ...

원래 답변 :
Application_Error()메소드가 호출되지 않는지 알아 냈습니다 ...

Global.asax.cs

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

기본적으로 (새 프로젝트가 생성 될 때) MVC 응용 프로그램에는 Global.asax.cs파일에 일부 논리가 있습니다. 이 논리는 경로를 매핑하고 필터를 등록하는 데 사용됩니다. 기본적으로 하나의 필터 (필터) 만 등록 HandleErrorAttribute합니다. customErrors가 켜져 있거나 RemoteOnly로 설정된 경우 원격 요청을 통해 handleErrorAttribute는 MVC에 오류보기를 찾도록 지시하고 Application_Error()메서드를 호출하지 않습니다 . 나는 이것에 대한 문서를 찾을 수 없지만 programmers.stackexchange.com에 대한이 답변에 설명되어 있습니다.

처리되지 않은 모든 예외에 대해 ApplicationError () 메서드를 호출 하려면 HandleErrorAttribute 필터를 등록하는 행을 간단히 제거하십시오.

이제 문제는 : 원하는 것을 얻도록 customErrors를 구성하는 방법입니다 ...

customErrors 섹션의 기본값은 redirectMode="ResponseRedirect"입니다. defaultRedirect 속성을 MVC 경로로 지정할 수도 있습니다. 매우 간단한 ErrorController를 만들고 web.config를 다음과 같이 변경했습니다 ...

web.config

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

이 솔루션의 문제점은 오류 URL로 302 경로 재 지정을 수행 한 다음 해당 페이지가 200 상태 코드로 응답한다는 것입니다. 이로 인해 Google은 잘못된 오류 페이지를 색인 생성합니다. 또한 HTTP 사양을 준수하지 않습니다. 내가하고 싶은 것은 리디렉션하지 않고 사용자 정의 오류보기로 원래 응답을 덮어 씁니다.

나는 변화를 시도했다 redirectMode="ResponseRewrite". 불행히도이 옵션은 MVC 경로를 지원하지 않으며 정적 HTML 페이지 또는 ASPX 만 지원 합니다. 처음에는 정적 HTML 페이지를 사용하려고했지만 응답 코드는 여전히 200이지만 적어도 리디렉션되지 않았습니다. 그런 다음 이 대답 에서 아이디어를 얻었습니다 ...

오류 처리를 위해 MVC를 포기하기로 결정했습니다. 나는 생성 Error.aspx과를 PageNotFound.aspx. 이 페이지는 매우 간단했지만 한 가지 마법이있었습니다.

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

이 블록은 페이지에 올바른 상태 코드가 제공되도록 지시합니다. 거칠게도 PageNotFound.aspx 페이지에서 HttpStatusCode.NotFound대신 사용 했습니다. web.config를 다음과 같이 변경했습니다 ...

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

모두 완벽하게 작동했습니다!

요약:

  • 라인을 제거하십시오. filters.Add(new HandleErrorAttribute());
  • Application_Error()방법을 사용 하여 예외 기록
  • ASPX 페이지를 가리키는 ResponseRewrite와 함께 customErrors 사용
  • ASPX 페이지가 자체 응답 상태 코드를 담당하도록합니다.

이 솔루션에 주목 한 몇 가지 단점이 있습니다.

  • ASPX 페이지는 Razor 템플릿과 마크 업을 공유 할 수 없으므로 웹 사이트의 표준 머리글 및 바닥 글 마크 업을 다시 작성하여 일관된 모양과 느낌을 유지해야했습니다.
  • * .aspx 페이지는 URL을 눌러 직접 액세스 할 수 있습니다

이러한 문제에 대한 해결 방법이 있지만 추가 작업을 수행하기에 충분히 걱정하지 않았습니다.

이것이 모두에게 도움이되기를 바랍니다!


ExceptionFilter를 만들고 Application_Error 대신 오류를 기록 하여이 문제를 해결했습니다. 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());
}

I found an article which describes a much cleaner way of making custom error pages in an MVC3 web app which does not prevent the ability to log the exceptions.

The solution is to use the <httpErrors> element of the <system.webServer> section.

I configured my Web.config like so...

<httpErrors errorMode="DetailedLocalOnly" existingResponse="Replace">
  <remove statusCode="404" subStatusCode="-1" />
  <remove statusCode="500" subStatusCode="-1" />
  <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
  <error statusCode="500" path="/Error" responseMode="ExecuteURL" />
</httpErrors>

I also configured customErrors to have mode="Off" (as suggested by the article).

That makes the responses overriden by an ErrorController's actions. Here is that controller:

public class ErrorController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult NotFound()
    {
        return View();
    }
}

The views are very straight forward, I just used standard Razor syntax to create the pages.

That alone should be enough for you to use custom error pages with MVC.

I also needed logging of Exceptions so I stole the Mark's solution of using a custom ExceptionFilter...

public class ExceptionPublisherExceptionFilter : IExceptionFilter
{
    public void OnException(ExceptionContext exceptionContext)
    {
        var exception = exceptionContext.Exception;
        var request = exceptionContext.HttpContext.Request;
        // log stuff
    }
}

The last thing you need to so is register the Exception Filter in your Global.asax.cs file:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new ExceptionPublisherExceptionFilter());
    filters.Add(new HandleErrorAttribute());
}

This feels like a much cleaner solution than my previous answer and works just as well as far as I can tell. I like it especially because it didn't feel like I was fighting against the MVC framework; this solution actually leverages it!


In case of ASP.NET MVC5 use

public class ExceptionPublisherExceptionFilter : IExceptionFilter
    {
        private static Logger _logger = LogManager.GetCurrentClassLogger();
        public void OnException(ExceptionContext exceptionContext)
        {
            var exception = exceptionContext.Exception;
            var request = exceptionContext.HttpContext.Request;
            // HttpException httpException = exception as HttpException;
            // Log this exception with your logger
            _logger.Error(exception.Message);
        }
    }

You can find it in FilterConfig.cs of App_Start folder.


I like Mark's answer with the ExceptionFilter, but another option, if you have all your controllers derive from the same base controller, is to simply override OnException in your base controller. You can do your logging and emailing there. This has the advantage of being able to use whatever dependencies you've already got injected into your base controller with your IoC container.

You can still use your IoC with an IExceptionFilter, but it's a bit more tricky to configure your bindings.


As far as I know, you are passing control over to the Page specified in the url parameter and your event notification would sit in here, rather than Application_Error

<customErrors defaultRedirect="myErrorPage.aspx"
              mode="On">
</customErrors>

A lot of information can be found here: http://support.microsoft.com/kb/306355


To get around this I ended up leaving customerrors disabled and handling all errors from the Application_Error event in global.asax. It's slightly tricky with MVC as I didn't want to return a 301 redirect, I wanted to return suitable error codes. More details can be viewed on my blog at http://www.wduffy.co.uk/blog/using-application_error-in-asp-net-mvcs-global-asax-to-handle-errors/ but the final code is listed below...

void Application_Error(object sender, EventArgs e)
{
    var error = Server.GetLastError();
    var code = (error is HttpException) ? (error as HttpException).GetHttpCode() : 500;

    if (code != 404)
    {
            // Generate email with error details and send to administrator
    }

    Response.Clear();
    Server.ClearError();

    string path = Request.Path;
    Context.RewritePath(string.Format("~/Errors/Http{0}", code), false);
    IHttpHandler httpHandler = new MvcHttpHandler();
    httpHandler.ProcessRequest(Context);
    Context.RewritePath(path, false);
}

And here is the controller

public class ErrorsController : Controller
{

    [HttpGet]
    public ActionResult Http404(string source)
    {
            Response.StatusCode = 404;
            return View();
    }

    [HttpGet]
    public ActionResult Http500(string source)
    {
            Response.StatusCode = 500;
            return View();
    }

}

This blog entry helped me:

http://asp-net.vexedlogic.com/2011/04/23/asp-net-maximum-request-length-exceeded/

If you're using IIS 7.0 or higher, you can alter your Web.config file to handle requests that are too large. There are some caveats, but here is an example:

<system.webServer>
  <security>
    <requestFiltering>
      <requestLimits maxAllowedContentLength="1048576" />
    </requestFiltering>
  </security>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="13" />
    <error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="/UploadTooLarge.htm" responseMode="Redirect" />
  </httpErrors>
</system.webServer>

There are additional details about these config file elements here:

http://www.iis.net/ConfigReference/system.webServer/security/requestFiltering/requestLimits

Status code 404.13 is defined as "Content Length Too Large". One important thing to note is that the maxAllowedContentLength is specified in bytes. This is different from the maxRequestLength setting you find in the <system.web> section, which is specified in kilobytes.

<system.web>
  <httpRuntime maxRequestLength="10240" />
</system.web>

Also note that the path attribute must be an absolute path when the responseMode is Redirect, so prepend the virtual directory name, if relevant. Jesse Webb's informative answers show how to do this with responseMode="ExecuteURL", and I would think that approach would work well, too.

This approach does not work if you're developing using the Visual Studio Development Server (Cassini, the Web server integrated into Visual Studio). I'm assuming it would work in IIS Express, but I haven't tested that.


I was having the same problem where Application_Error() wasn't getting hit. I tried everything, until finally I stepped through what was happening. I had some custom code in an ELMAH event that was adding JSON to the email it sends, and there was a null error in there!

Fixing the internal error allowed the code to continue on to the Application_Error() event as expected.

참고URL : https://stackoverflow.com/questions/6508415/application-error-not-firing-when-customerrors-on

반응형