customerrors = "On"일 때 Application_Error가 발생하지 않음


124

오류가 발생할 때 실행되는 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


나는 똑같은 문제가 있습니다. 나는 또한이 SO 질문을 발견했습니다 : stackoverflow.com/questions/3713939/… 이것은 IIS7 서버를 클래식 모드로 전환하도록 제안합니다. 불행히도 그것은 우리에게 옵션이 아닙니다. 누구보다 더 나은 솔루션이 있습니까?
Jesse Webb

여기에 또 다른 관련 질문이며 대답을 (허용됩니다 어느 것도) 모든 ...에함으로써 Application_Error ()를 사용하지 않는 것이 좋습니다의 stackoverflow.com/questions/1194578/...
제시 웹의

@Gweebz 나는이 문제를 어떻게 해결했는지에 대한 답변을 게시했지만, 왜이 행동이 발생했는지에 대한 확실한 문서를 찾지 못했습니다.
WDuffy 2011

Application_Error()메서드가 호출되지 않은 이유를 설명하는 답변을 추가했습니다 . 또한 최종 솔루션을 설명했습니다.
Jesse Webb

사용자 지정 오류가 작동하도록하려면 이 문서 를 정말 권장 합니다 .
ThomasArdal

답변:


133

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

원래 답변 : 메서드가 호출되지 않는
이유를 알아 냈습니다 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.aspxPageNotFound.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을 눌러 직접 액세스 할 수 있습니다.

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

모두에게 도움이 되었기를 바랍니다.


2
+1! 정말 좋은 해결 방법이지만 MVC를 aspx 페이지와 혼합하면 어떤 결과가 발생할 수 있습니까?
Diego

2
우리는 지금까지 몇 달 동안 PROD에서 이것을 가지고 있었지만 나는 부정적인 영향을 발견하지 못했습니다. 유일한 '문제'는 MVC가 필요하지 않지만 .as 파일 을 추가 할 때 필요하기 때문에 AspCompile MSBUILD 작업을 수행하기 위해 CI를 변경하고 배포해야한다는 것입니다. 이 다른 문제가있을 수 있지만 ... 아직 표면화되지 않은
제시 웹이에게

나는 MVC4 에서이 접근 방식을 사용하려고 노력해 왔으며 분명히 <customErrors mode="Off" />. 갖는 filters.Add(new HandleErrorAttribute());제거 여부를 아무런 효과가 없습니다.
Grzegorz Sławecki

aspx 페이지에서 표시하려는 뷰를 호출하기 위해 ajax 호출을 추가 할 수 있습니다. 코드를 복제 할 필요가 없습니다
Mike

71

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());
}

6
+1이 답변이 작동한다면 오류를 처리하는 가장 우아하고 의도 된 방법 (MVC 프레임 워크에 의해) 인 것 같습니다.
Matt Hamsmith

2
이것은 나를 위해 완벽하게 작동하며 여기에서 받아 들여지는 대답보다 훨씬 깔끔합니다. 좋은!
Alex Warren

3
이것은 예외 로깅 문제를 해결하는 데 효과적입니다. 이것을 사용자 정의 오류 페이지 표시와 어떻게 결합 했습니까?
Jesse Webb

3
나는 이것을 시도했고 404의 경우를 제외하고는 잘 작동했습니다. 404의 경우 Errors.cshtml보기를 표시하지 않고 YSoD 만 제공합니다. 맞춤형 404가 필요하지 않은 경우이 솔루션은 확실히 더 깨끗합니다!
Jesse Webb 2012 년

1
나는 그것을 좋아한다. 'CustomErrors = On'작업
Illidan

36

예외를 기록하는 기능을 방해하지 않는 MVC3 웹 앱에서 사용자 지정 오류 페이지를 만드는 훨씬 더 깨끗한 방법을 설명 하는 기사 를 찾았습니다 .

해결책은 섹션 의 <httpErrors>요소 를 사용하는 것 <system.webServer>입니다.

Web.config를 이렇게 구성했습니다 .

<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>

나는 또한 (기사에서 제안한대로) customErrors갖도록 구성 했습니다 mode="Off".

그러면 응답이 ErrorController의 작업에 의해 재정의됩니다. 컨트롤러는 다음과 같습니다.

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

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

보기는 매우 간단하며 표준 Razor 구문을 사용하여 페이지를 만들었습니다.

이것만으로도 MVC에서 사용자 지정 오류 페이지를 사용할 수 있습니다.

또한 예외 로깅이 필요했기 때문에 사용자 지정 ExceptionFilter를 사용하는 Mark의 솔루션 을 훔쳤습니다 .

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

마지막으로 필요한 것은 Global.asax.cs 파일 에 예외 필터를 등록하는 것입니다 .

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

이것은 이전 답변보다 훨씬 깨끗한 솔루션처럼 느껴지며 내가 말할 수있는 한 잘 작동합니다. MVC 프레임 워크에 맞서 싸우는 것 같지 않았기 때문에 특히 마음에 듭니다. 이 솔루션은 실제로 그것을 활용합니다!


6
이 솔루션은 IIS 7 이상에서만 작동한다고 생각합니다. httpErrors 요소는 최근에 추가되었습니다.
Jesse Webb 2012 년

이 대답은 나를 위해 일을하지 않았다, 나, 그것은 나에게 무서운 파란 게임이 HTTP Error 500.0 - Internal Server Error The page cannot be displayed because an internal server error has occurred. 오류 화면, 나의 요청 /Error/Index페이지
Serj 세이건

@SerjSagan 나는 단계를 테스트하기 위해 새 프로젝트에서 이것을 시도했으며 잘 작동합니다. IIS, IIS Express 또는 VS Dev Server를 사용하고 있습니까? 이것은 VS Dev Server에서 작동하지 않습니다. IIS가 아닌 VS Dev Server를 사용하도록 프로젝트를 설정했을 때 사용자 지정 오류 페이지 대신 노란색 화면 오류를 발견했습니다.
Jesse Webb

1
@SerjSagan 그러나 고전적인 노란색 화면 오류와 달리 IIS 파란색 화면 오류가 발생하는 것처럼 들립니다. 이것은 당신이 어떤 형태의 IIS를 사용하고 있다고 가정하게 만듭니다. 그렇다면 첫 번째 문장, 특히 마지막 섹션 인 "중요한 몇 가지 사항"에서 링크 한 기사를 읽어보십시오. 그것은 말한다 :To able to overwrite global settings in global IIS settings (file: C:\Windows\System32\inetsrv\config \applicationHost.config) should be: <section name="httpErrors" overrideModeDefault="Allow" />
제시 웹의

3
@SerjSagan errorMode를 DetailedLocalOnly 또는 Custom으로 변경하면 페이지가 표시됩니다.
Daniel P

8

의 경우 ASP.NET MVC5의 사용

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);
        }
    }

당신은에서 찾을 수 FilterConfig.csApp_Start폴더.


1

나는 ExceptionFilter에 대한 Mark의 대답을 좋아하지만 모든 컨트롤러가 동일한 기본 컨트롤러에서 파생 된 경우 다른 옵션은 기본 컨트롤러에서 OnException을 재정의하는 것입니다. 거기에서 로깅 및 이메일을 보낼 수 있습니다. 이것은 IoC 컨테이너를 사용하여 기본 컨트롤러에 이미 주입 한 종속성을 사용할 수 있다는 장점이 있습니다.

여전히 IoC를 IExceptionFilter와 함께 사용할 수 있지만 바인딩을 구성하는 것이 조금 더 까다 롭습니다.


0

내가 아는 한, url 매개 변수에 지정된 Page에 제어권을 전달하고 이벤트 알림이 Application_Error가 아닌 여기에 있습니다.

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

많은 정보는 다음에서 찾을 수 있습니다. http://support.microsoft.com/kb/306355


Chris에게 감사합니다. 문서를 읽었으며 처리되지 않은 오류가 발생할 때 Application_Error가 호출되고 (내가 예상하는) Server.ClearError ()가 web.config customErrors 섹션으로 호출되지 않아야 최종 처리 지점이 될 것이라고 제안합니다. 그러나 customErrors를 활성화하면 Application_Error가 발생하지 않습니다.
WDuffy 2011-06-28

링크 한 문서는 ASP.NET 응용 프로그램에 대해 설명하고 있으며 MVC3 웹 응용 프로그램이 다르게 작동하는 것으로 보입니다.
Jesse Webb

0

이 문제를 해결하기 위해 사용자 지정 오류를 비활성화하고 global.asax의 Application_Error 이벤트에서 발생하는 모든 오류를 처리했습니다. 301 리디렉션을 반환하고 싶지 않았기 때문에 MVC에서는 약간 까다 롭고 적절한 오류 코드를 반환하고 싶었습니다. 자세한 내용은 내 블로그 ( http://www.wduffy.co.uk/blog/using-application_error-in-asp-net-mvcs-global-asax-to-handle-errors/) 에서 볼 수 있지만 최종 코드는 다음과 같습니다. 아래에 나열 ...

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);
}

그리고 여기에 컨트롤러가 있습니다.

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();
    }

}

나는 당신의 해결책을 시도했지만 그것은 나를 위해 작동하지 않았습니다. 줄을 사용하면에 Response.StatusCode = ###;내장 MVC 오류 페이지가 표시됩니다 C:\inetpub\custerr\en-US. 또한 Application_Error () 메서드에서 HttpHandlers 또는 컨트롤러를 수동으로 호출하는 아이디어가 마음에 들지 않았습니다. 나는 당신이 당신의 문제에 대한 해결책을 찾았다는 것을 기쁘게 생각합니다. 나는 이것이 나에게 어떤 종류의 두통을 주 었는지 압니다.
Jesse Webb

0

이 블로그 항목이 도움이되었습니다.

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

IIS 7.0 이상을 사용하는 경우 너무 큰 요청을 처리하도록 Web.config 파일을 변경할 수 있습니다. 몇 가지주의 사항이 있지만 여기에 예가 있습니다.

<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>

여기에 이러한 구성 파일 요소에 대한 추가 세부 정보가 있습니다.

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

상태 코드 404.13은 "콘텐츠 길이가 너무 큼"으로 정의됩니다. 한 가지 중요한 점은이 maxAllowedContentLength바이트 단위로 지정 된다는 것 입니다. 이것은 KB 단위로 지정된 섹션 maxRequestLength에서 찾은 설정 과 다릅니다 <system.web>.

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

또한주의 path(가) 때 속성이 절대 경로 여야합니다 responseMode입니다 Redirect관련 그래서 만약, 가상 디렉터리 이름 앞에 추가. Jesse Webb의 유익한 답변은를 사용하여이를 수행하는 방법을 보여 주며 responseMode="ExecuteURL", 그 접근 방식도 잘 작동 할 것이라고 생각합니다.

Visual Studio 개발 서버 (Visual Studio에 통합 된 웹 서버 인 Cassini)를 사용하여 개발하는 경우에는이 방법이 작동하지 않습니다. IIS Express에서 작동한다고 가정하고 있지만 테스트하지는 않았습니다.


0

나는 같은 문제를 겪고 있었다. Application_Error() 맞지 않는 있었다. 나는 모든 것을 시도했고 마침내 무슨 일이 일어나고 있는지를 밟았다. 보내는 이메일에 JSON을 추가하는 ELMAH 이벤트에 사용자 지정 코드가 있었고 거기에 null 오류가있었습니다!

내부 오류를 수정하면 코드가 Application_Error()예상대로 이벤트 를 계속 진행할 수있었습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.