asp.net MVC3의 사용자 정의 오류 페이지


144

MVC3 기본 웹 사이트를 개발 중이며 오류 처리 및 각 종류의 오류에 대한 커스텀 뷰 렌더링을위한 솔루션을 찾고 있습니다. 따라서 그의 주요 동작이 "Index"(일반 오류 페이지) 인 "Error"컨트롤러가 있고이 컨트롤러에 "Handle500"또는 "HandleActionNotFound"와 같이 사용자에게 나타날 수있는 오류에 대한 몇 가지 추가 조치가있을 것입니다.

따라서 웹 사이트에서 발생할 수있는 모든 오류는이 "오류"컨트롤러에 의해 처리 될 수 있습니다 (예 : "컨트롤러"또는 "액션"을 찾을 수 없음, 500, 404, dbException 등).

Sitemap 파일을 사용하여 웹 사이트 경로를 정의하고 경로를 지정하지 않습니다.

이 질문에 이미 답변되었습니다, 이것은 Gweebz의 답변입니다

내 마지막 applicaiton_error 방법은 다음과 같습니다.

protected void Application_Error() {
//while my project is running in debug mode
if (HttpContext.Current.IsDebuggingEnabled && WebConfigurationManager.AppSettings["EnableCustomErrorPage"].Equals("false"))
{
    Log.Logger.Error("unhandled exception: ", Server.GetLastError());
}
else
{
    try
    {
        var exception = Server.GetLastError();

        Log.Logger.Error("unhandled exception: ", exception);

        Response.Clear();
        Server.ClearError();
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "General";
        routeData.Values["exception"] = exception;

        IController errorsController = new ErrorsController();
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        errorsController.Execute(rc);
    }
    catch (Exception e)
    {
        //if Error controller failed for same reason, we will display static HTML error page
        Log.Logger.Fatal("failed to display error page, fallback to HTML error: ", e);
        Response.TransmitFile("~/error.html");
    }
}
}

이를 지원하기 위해 web.config에 어떤 설정이 있어야합니까? 아마도 httperrors 설정을 포함하지 않았습니까?
philbird

forums.asp.net/p/1782402/4894514.aspx/… IE와 같은 멋진 팁이 512 바이트 미만인 경우 오류 페이지를 표시하지 않습니다.
RickAndMSFT

답변:


201

다음은 사용자 지정 오류를 처리하는 방법의 예입니다. ErrorsController다른 HTTP 오류를 처리 하는 with 액션을 정의 합니다.

public class ErrorsController : Controller
{
    public ActionResult General(Exception exception)
    {
        return Content("General failure", "text/plain");
    }

    public ActionResult Http404()
    {
        return Content("Not found", "text/plain");
    }

    public ActionResult Http403()
    {
        return Content("Forbidden", "text/plain");
    }
}

그런 다음 Application_Errorin을 구독 Global.asax하고이 컨트롤러를 호출합니다.

protected void Application_Error()
{
    var exception = Server.GetLastError();
    var httpException = exception as HttpException;
    Response.Clear();
    Server.ClearError();
    var routeData = new RouteData();
    routeData.Values["controller"] = "Errors";
    routeData.Values["action"] = "General";
    routeData.Values["exception"] = exception;
    Response.StatusCode = 500;
    if (httpException != null)
    {
        Response.StatusCode = httpException.GetHttpCode();
        switch (Response.StatusCode)
        {
            case 403:
                routeData.Values["action"] = "Http403";
                break;
            case 404:
                routeData.Values["action"] = "Http404";
                break;
        }
    }

    IController errorsController = new ErrorsController();
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
    errorsController.Execute(rc);
}

4
약간의 메모. 각 ActionResult에 대해 각 경우 (404, 500 등)에서 View를 렌더링하고 싶었으므로 View를 반환했습니다. 그러나 Application_Error 내용을 시도했지만 정적 HTML 페이지가 실패하는 경우가 있습니다. (누군가 원하는 경우 코드를 게시 할 수 있습니다)
John Louros

4
MVC3 에서이 솔루션을 사용하여 면도기를 렌더링 할 수 없습니다. 예를 들어 반환보기 (모델)는 빈 화면 만 가져옵니다.
Extrakun

2
통합 IIS7을 위해 TrySkipIisCustomErrors를 수정했습니다. 참조 stackoverflow.com/questions/1706934/...
파벨 Savara

1
@ajbeaven ExecuteIController인터페이스에 정의 된 메소드 입니다. 이것은 보호 될 수 없습니다. 내 코드를보다 신중하게 살펴보고 메소드 를 호출하는 변수 IController errorsController = new ErrorsController();의 유형을 확인하십시오 . 유형 이 있으므로이 메소드를 호출하는 데 방해가되는 것은 없습니다. 방식에 의해 그리고 MVC 3에서뿐만 아니라 컨트롤러 클래스에서 보호, 그래서이 점에 변화가 없다. errorsControllerExecuteIControllerExecute
Darin Dimitrov

2
응답의 내용 유형을 명시 적으로 지정하여 수정했습니다.Response.ContentType = "text/html";
ajbeaven


6

Web.Config 파일에서이 작업을 수행 할 수도 있습니다. 다음은 IIS 7.5에서 작동하는 예입니다.

     <system.webServer>
          <httpErrors errorMode="DetailedLocalOnly" defaultResponseMode="File">
                <remove statusCode="502" subStatusCode="-1" />
                <remove statusCode="501" subStatusCode="-1" />
                <remove statusCode="412" subStatusCode="-1" />
                <remove statusCode="406" subStatusCode="-1" />
                <remove statusCode="405" subStatusCode="-1" />
                <remove statusCode="404" subStatusCode="-1" />
                <remove statusCode="403" subStatusCode="-1" />
                <remove statusCode="401" subStatusCode="-1" />
                <remove statusCode="500" subStatusCode="-1" />
                <error statusCode="500" path="/notfound.html" responseMode="ExecuteURL" />
                <error statusCode="401" prefixLanguageFilePath="" path="/500.html" responseMode="ExecuteURL" />
                <error statusCode="403" prefixLanguageFilePath="" path="/403.html" responseMode="ExecuteURL" />
                <error statusCode="404" prefixLanguageFilePath="" path="/404.html" responseMode="ExecuteURL" />
                <error statusCode="405" prefixLanguageFilePath="" path="/405.html" responseMode="ExecuteURL" />
                <error statusCode="406" prefixLanguageFilePath="" path="/406.html" responseMode="ExecuteURL" />
                <error statusCode="412" prefixLanguageFilePath="" path="/412.html" responseMode="ExecuteURL" />
                <error statusCode="501" prefixLanguageFilePath="" path="/501.html" responseMode="ExecuteURL" />
                <error statusCode="502" prefixLanguageFilePath="" path="/genericerror.html" responseMode="ExecuteURL" />
           </httpErrors>
</system.webServer>

3

구성 값을 추가했으며 오류 처리를 실행할지 여부 EnableCustomErrorPage도 확인하고 있습니다 IsDebuggingEnabled.

<customErrors/>ASP.NET 에는 이미 이러한 목적을위한 구성이 있으므로 다음과 같이 말하는 것이 가장 쉽습니다.

    protected void Application_Error()
    {
        if (HttpContext.Current == null) 
        {
                // errors in Application_Start will end up here                
        }
        else if (HttpContext.Current.IsCustomErrorEnabled)
        {
                // custom exception handling
        }
    }

그런 다음 구성에서 <customErrors mode="RemoteOnly" /> 에서 배포가 안전하고 사용자 정의 오류 페이지를 테스트해야 할 때 <customErrors mode="On" />작동하는지 확인할 수 있도록 설정했습니다 .

활성 컨텍스트는 없지만이 메소드 HttpContext.Current에서 예외 Application_Start가 여전히이 메소드 이므로 여전히 널인지 확인해야합니다 .


2

Jeff Atwood의 사용자 친화적 인 예외 처리 모듈 을 구현하여 올바른 http 상태 코드와 함께 사용자 친화적 인 오류 페이지를 표시 할 수 있습니다. 약간 수정하여 을 . 리디렉션없이 작동합니다. 코드는 2004 (!) 코드이지만 MVC와 잘 작동합니다. MVC 프로젝트 소스 코드 변경없이 web.config에서 완전히 구성 할 수 있습니다.

상태가 아닌 원래 HTTP 상태를 반환하는 데 필요한 수정 사항 200이 관련 포럼 게시물에 설명되어 있습니다.

기본적으로 Handler.vb에서 다음과 같은 내용을 추가 할 수 있습니다.

' In the header...
Private _exHttpEx As HttpException = Nothing

' At the top of Public Sub HandleException(ByVal ex As Exception)...
HttpContext.Current.Response.StatusCode = 500
If TypeOf ex Is HttpException Then
    _exHttpEx = CType(ex, HttpException)
    HttpContext.Current.Response.StatusCode = _exHttpEx.GetHttpCode()
End If

0

MVC 4.5를 사용하고 있으며 Darin의 솔루션에 문제가있었습니다. 참고 : Darin의 솔루션은 우수하며 솔루션을 사용하는 데 사용했습니다. 다음은 수정 된 솔루션입니다.

protected void Application_Error(object sender, EventArgs e)
{           
var exception = Server.GetLastError();
var httpException = exception as HttpException;
Response.StatusCode = httpException.GetHttpCode();

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


if (httpException != null)
{
    var httpContext = HttpContext.Current;

    httpContext.RewritePath("/Errors/InternalError", false);

    // MVC 3 running on IIS 7+
    if (HttpRuntime.UsingIntegratedPipeline)
    {
        switch (Response.StatusCode)
        {
            case 403:
                httpContext.Server.TransferRequest("/Errors/Http403", true);
                break;
            case 404:
                httpContext.Server.TransferRequest("/Errors/Http404", true);
                break;
            default:
                httpContext.Server.TransferRequest("/Errors/InternalError", true);
                break;
        }
    }
    else
    {
        switch (Response.StatusCode)
        {
            case 403:
                httpContext.RewritePath(string.Format("/Errors/Http403", true));
                break;
            case 404:
                httpContext.RewritePath(string.Format("/Errors/Http404", true));
                break;
            default:
                httpContext.RewritePath(string.Format("/Errors/InternalError", true));
                break;
        }

        IHttpHandler httpHandler = new MvcHttpHandler();
        httpHandler.ProcessRequest(httpContext);
    }
}
}

2
Darin의 솔루션에 어떤 문제가 있었습니까?
Kenny Evitt

귀하는 귀하가 경험 한 문제에 대해 경쟁 답변을 제시하지 않았습니다.
ivanjonas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.