2009-04-04 3 views
119

가능한 중복은 :
How can I properly handle 404 in ASP.NET MVC?ASP.NET MVC (404) 오류 처리

나는 404 Http error handler in Asp.Net MVC (RC 5)에 설명 된 변경 한 나는 여전히 표준 404 오류 페이지를 얻고있다. IIS에서 무엇인가를 변경해야합니까?

+1

다음 항목을 잘 읽으십시오 @ [ASP.NET MVC 4에서 404 찾을 수없는 오류를 효과적으로 처리하는 방법] (http://yassershaikh.com/how-to-handle-404-not-found-errors -effectively-with-asp-net-mvc-4 /) – Yasser

답변

131

.

404 오류 정보와 함께 ErrorControllers 또는 정적 페이지를 추가하십시오.

web.config (컨트롤러의 경우)를 수정하십시오.

<system.web> 
    <customErrors mode="On" > 
     <error statusCode="404" redirect="~/Errors/Error404" /> 
    </customErrors> 
</system.web> 

또는이 모두 놓친 경로를 처리하고 작업을 놓친 것

<system.web> 
    <customErrors mode="On" > 
     <error statusCode="404" redirect="~/Static404.html" /> 
    </customErrors> 
</system.web> 

정적 페이지의 경우

.

+2

니스! :) ErrorsController는 다른 모든 컨트롤러와 같은베이스에서 상속받을 수 있으므로 특정 기능에 액세스 할 수 있습니다. 또한 Error404보기는 추가 작업없이 사이트의 나머지 부분에 대한 전반적인 모양과 느낌을 사용자에게 제공하는 마스터에 래핑 될 수 있습니다. – Dimskiy

+7

개발 중에 실제 오류 페이지를 보려면''를 사용하십시오. –

+1

이것은 맞습니다. Response.Clear()를 호출하지 마십시오. Mike Chaliy이 제안한대로 http://blogs.msdn.com/b/rickandy/archive/2012/03/01/response-redirect-and-asp-net-mvc-do-not-mix.aspx – RickAndMSFT

0

IIS에서 오류 코드를 기반으로 "특정"페이지로 리디렉션을 지정할 수 있습니다. 예를 들어, 404 -> 사용자 정의 된 404 오류 페이지를 구성 할 수 있습니다.

1

필자가 FilterAttribute를 살펴 보는 것이 좋습니다. 예를 들어, MVC는 이미 HandleErrorAttribute를 가지고 있습니다. 당신은 단지 404를 처리하기 위해 그것을 사용자 정의 할 수 있습니다. 당신이 interesed 있다면 답장 예를 들어 보겠습니다.

BTW 당신은 ​​상황의 대부분에서 작동하지 않는 이전 질문에서 수락 (마지막 경로 포함)

솔루션. HandleUnknownAction의 두 번째 해결 방법은 작동하지만 각 컨트롤러에서이 변경을 수행하거나 단일 기본 컨트롤러를 필요로합니다.

내 선택은 HandleUnknownAction을 사용한 솔루션입니다.

+0

"{controller}/{action}/{id}"의 표준 기본 경로가 everythgin을 잡아서 문제를 해결하지 못하는 것 같습니다. 마지막 경로. 나는 컨트롤러가 다음 경로를 평가할 수 없다는 것을 발견 할 수 없다고 생각했다. – Clearly

+0

HandleUnknownAction은 foudn되지 않은 작업에서만 작동합니다. 라우트가 조정되었지만 결과로 나오는 컨트롤러를 찾을 수 없으면 어떻게해야합니까? 그걸 처리하는 가장 좋은 방법은 무엇입니까? – Clearly

+0

예, 조치가 발견되지 않는 경우에만 정확합니다. 두 가지 솔루션을 결합 할 수 있습니다. 누락 된 작업 및 놓친 컨트롤러의 경로에 대한 HandleUnknownAction. 다른 가능한 솔루션은 사용자 지정 RouteHandler입니다. –

340

내가 제대로 MVC (특히 MVC3)에 404을 관리하는 방법에 많이을 조사했으며,이, 이럴 내가 함께 왔어요 최고의 솔루션입니다 :

의 Global.asax에서 :

public class MvcApplication : HttpApplication 
{ 
    protected void Application_EndRequest() 
    { 
     if (Context.Response.StatusCode == 404) 
     { 
      Response.Clear(); 

      var rd = new RouteData(); 
      rd.DataTokens["area"] = "AreaName"; // In case controller is in another area 
      rd.Values["controller"] = "Errors"; 
      rd.Values["action"] = "NotFound"; 

      IController c = new ErrorsController(); 
      c.Execute(new RequestContext(new HttpContextWrapper(Context), rd)); 
     } 
    } 
} 

ErrorsController :

public sealed class ErrorsController : Controller 
{ 
    public ActionResult NotFound() 
    { 
     ActionResult result; 

     object model = Request.Url.PathAndQuery; 

     if (!Request.IsAjaxRequest()) 
      result = View(model); 
     else 
      result = PartialView("_NotFound", model); 

     return result; 
    } 
} 

편집 :

IoC를 사용하는 경우 (예 :AutoFac), 사용 컨트롤러를 작성해야합니다 :) (선택

var rc = new RequestContext(new HttpContextWrapper(Context), rd); 
var c = ControllerBuilder.Current.GetControllerFactory().CreateController(rc, "Errors"); 
c.Execute(rc); 

대신

IController c = new ErrorsController(); 
c.Execute(new RequestContext(new HttpContextWrapper(Context), rd)); 

는 설명 :

6 개 시나리오는 내가 할 수있다 ASP.NET MVC3 앱이 404를 생성 할 수있는 위치를 생각해보십시오. ASP.NET에 의해 생성 된

:

  • 시나리오 1 : URL은 경로 테이블에 경로를 일치하지 않습니다. ASP.NET MVC에 의해 생성 된

:

  • 시나리오 2 : URL은 경로와 일치하지만 존재하지 않는 컨트롤러를 지정합니다.

  • 시나리오 3 : URL은 경로와 일치하지만 존재하지 않는 작업을 지정합니다. 수동 생성

:

  • 시나리오 4 : 동작이 HttpNotFound 방법을 사용하여 HttpNotFoundResult 반환한다().

  • 시나리오 5 : 수동 (404)

에 Response.StatusCode 속성을 수정 Actions (동작) : 액션은 404

  • 시나리오 6 상태 코드와 함께 HttpException을 던졌습니다목표

    • (A) 사용자에게 404 오류 페이지를 보여줍니다.

    • (B) 클라이언트 응답 (특히 SEO의 경우 중요)에서 404 상태 코드를 유지 관리하십시오.

    • (C) 302 리디렉션을 포함하지 않고 직접 응답을 보냅니다.

    해결 시도이 용액 정의 오류

    <system.web> 
        <customErrors mode="On"> 
         <error statusCode="404" redirect="~/Errors/NotFound"/> 
        </customError> 
    </system.web> 
    

    문제 : 시나리오

    • 객관적 (A)에 맞지 않는 (1), (4) (6).
    • 객관적인 (B)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.
    • 객관적인 (C)를 준수하지 않습니다.

    해결 시도 : HTTP 오류이 솔루션

    <system.webServer> 
        <httpErrors errorMode="Custom"> 
         <remove statusCode="404"/> 
         <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/> 
        </httpErrors> 
    </system.webServer> 
    

    문제 :

    • 만 IIS 7 +에서 작동합니다.
    • 시나리오 (2), (3), (5)의 목표 (A)를 준수하지 않습니다.
    • 객관적인 (B)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.

    해결 시도 :와 HTTP 오류는이 솔루션을

    <system.webServer> 
        <httpErrors errorMode="Custom" existingResponse="Replace"> 
         <remove statusCode="404"/> 
         <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/> 
        </httpErrors> 
    </system.webServer> 
    

    문제를 교체 :

    • 만 IIS 7 +에서 작동합니다.
    • 객관적인 (B)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.
    • 응용 프로그램 수준의 HTTP 예외를가립니다. 예 : customErrors 섹션, System.Web.Mvc.HandleErrorAttribute 등을 사용할 수 없습니다. 일반 오류 페이지 만 표시 할 수 없습니다.

    해결을 시도 customErrors에와 HTTP 오류이 솔루션

    <system.web> 
        <customErrors mode="On"> 
         <error statusCode="404" redirect="~/Errors/NotFound"/> 
        </customError> 
    </system.web> 
    

    <system.webServer> 
        <httpErrors errorMode="Custom"> 
         <remove statusCode="404"/> 
         <error statusCode="404" path="App/Errors/NotFound" responseMode="ExecuteURL"/> 
        </httpErrors> 
    </system.webServer> 
    

    문제 :

    • 만 IIS 7 +에서 작동합니다.
    • 객관적인 (B)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.
    • 시나리오 (2), (3), (5)의 목표 (C)를 준수하지 않습니다.

    이전에 문제가있는 사람도 자신의 라이브러리를 만들려고했습니다 (http://aboutcode.net/2011/02/26/handling-not-found-with-asp-net-mvc3.html 참조). 그러나 이전 솔루션은 외부 라이브러리를 사용하지 않고 모든 시나리오를 처리하는 것으로 보입니다.

  • +0

    새 프로젝트를 만들 때 MVC 템플릿이 자동으로 설정하는 HandleErrorAttribute와 함께 이것이 가장 간단하고 간단한 솔루션입니다. – s1mm0t

    +6

    당신의 분석은 좋아하지만 해결책은 아닙니다 :) 요청 끝까지 기다리는 것과 관련된 문제는 요청 컨텍스트 중 일부가 세션 상태와 같이 이미 버려진 것입니다. –

    +1

    Response.Clear와 MVC는 섞이지 않습니다.이 방법은 사용하지 마십시오. http://blogs.msdn.com/b/rickandy/archive/2012/03/01/response-redirect-and-asp-net-mvc-do -not-mix.aspx – RickAndMSFT

    5

    Marco의 응답이 가장 좋은 해결책입니다. 내 오류 처리를 제어 할 필요가 있었고 실제로 제어한다는 의미입니다. 물론 솔루션을 조금 확장하고 모든 것을 관리하는 전체 오류 관리 시스템을 만들었습니다. 나는 또한 다른 블로그에서이 솔루션에 대해 읽었으며 대부분의 고급 개발자들이 매우 수용할만한 것으로 보인다.

    여기 내가 사용하고 최종 코드 :

    protected void Application_EndRequest() 
        { 
         if (Context.Response.StatusCode == 404) 
         { 
          var exception = Server.GetLastError(); 
          var httpException = exception as HttpException; 
          Response.Clear(); 
          Server.ClearError(); 
          var routeData = new RouteData(); 
          routeData.Values["controller"] = "ErrorManager"; 
          routeData.Values["action"] = "Fire404Error"; 
          routeData.Values["exception"] = exception; 
          Response.StatusCode = 500; 
    
          if (httpException != null) 
          { 
           Response.StatusCode = httpException.GetHttpCode(); 
           switch (Response.StatusCode) 
           { 
            case 404: 
             routeData.Values["action"] = "Fire404Error"; 
             break; 
           } 
          } 
          // Avoid IIS7 getting in the middle 
          Response.TrySkipIisCustomErrors = true; 
          IController errormanagerController = new ErrorManagerController(); 
          HttpContextWrapper wrapper = new HttpContextWrapper(Context); 
          var rc = new RequestContext(wrapper, routeData); 
          errormanagerController.Execute(rc); 
         } 
        } 
    

    을 내 ErrorManagerController 내부 :

     public void Fire404Error(HttpException exception) 
        { 
         //you can place any other error handling code here 
         throw new PageNotFoundException("page or resource"); 
        } 
    

    지금, 내 행동에, 내가 만든 사용자 정의 예외를 throw하고있다. 내 컨트롤러는 내가 만든 사용자 지정 컨트롤러 기반 클래스에서 상속됩니다. 사용자 지정 기본 컨트롤러는 오류 처리를 무시하도록 작성되었습니다. 여기 내 사용자 지정 기본 컨트롤러 클래스 :

    public class MyBasePageController : Controller 
    { 
        protected override void OnException(ExceptionContext filterContext) 
        { 
         filterContext.GetType(); 
         filterContext.ExceptionHandled = true; 
         this.View("ErrorManager", filterContext).ExecuteResult(this.ControllerContext); 
         base.OnException(filterContext); 
        } 
    } 
    

    은 "의 ErrorManager"위의 코드에서이 ExceptionContext에 기초한 모델을 사용하고 단지보기입니다

    내 솔루션은 완벽하게 작동하고 나는 어떠한 처리 할 수 ​​있어요 내 웹 사이트에서 오류가 발생하여 예외 유형에 따라 다른 메시지가 표시됩니다.

    +1

    나는 당신에게 동의하지 않는다. 그것은 최고의 솔루션입니다. 이 작업과 같은 일반적인 작업은 설치가 복잡하지 않아야합니다. 마르코스의 대답은 훌륭하지만, 간단한 일들을위한 많은 코드를 잃어 버리지는 않습니다. – PussInBoots