Programing

ASP.NET MVC에서 404를 올바르게 처리하려면 어떻게해야합니까?

lottogame 2020. 2. 19. 21:17
반응형

ASP.NET MVC에서 404를 올바르게 처리하려면 어떻게해야합니까?


RC2를 사용하고 있습니다

URL 라우팅 사용 :

routes.MapRoute(
    "Error",
     "{*url}",
     new { controller = "Errors", action = "NotFound" }  // 404s
);

위의 요청은 다음과 같은 요청을 처리하는 것으로 보입니다 (초기 MVC 프로젝트에서 기본 경로 테이블 설정을 가정) : "/ blah / blah / blah / blah"

컨트롤러 자체에서 HandleUnknownAction () 재정의 :

// 404s - handle here (bad action requested
protected override void HandleUnknownAction(string actionName) {
    ViewData["actionName"] = actionName;
    View("NotFound").ExecuteResult(this.ControllerContext);
}  

그러나 이전 전략은 잘못된 / 알 수없는 컨트롤러에 대한 요청을 처리하지 않습니다. 예를 들어, 나는 "/ IDoNotExist"를 가지고 있지 않다. 이것을 요청하면 라우팅 + 오버라이드를 사용하면 웹 서버에서 일반 404 페이지를 얻는다.

마지막으로, 내 질문은 : MVC 프레임 워크 자체에서 경로 또는 다른 것을 사용하여 이러한 유형의 요청을 잡을 수있는 방법이 있습니까?

또는 기본적으로 Web.Config customErrors를 404 처리기로 사용 하고이 모든 것을 잊어 버려야합니까? customErrors를 사용하면 직접 액세스에 대한 Web.Config 제한으로 인해 / Views 외부에 일반 404 페이지를 저장해야한다고 가정합니다.


코드는 http://blogs.microsoft.co.il/blogs/shay/archive/2009/03/06/real-world-error-hadnling-in-asp-net-mvc-rc2.aspx 에서 가져와 작동합니다 ASP.net MVC 1.0에서도

http 예외를 처리하는 방법은 다음과 같습니다.

protected void Application_Error(object sender, EventArgs e)
{
   Exception exception = Server.GetLastError();
   // Log the exception.

   ILogger logger = Container.Resolve<ILogger>();
   logger.Error(exception);

   Response.Clear();

   HttpException httpException = exception as HttpException;

   RouteData routeData = new RouteData();
   routeData.Values.Add("controller", "Error");

   if (httpException == null)
   {
       routeData.Values.Add("action", "Index");
   }
   else //It's an Http Exception, Let's handle it.
   {
       switch (httpException.GetHttpCode())
       {
          case 404:
              // Page not found.
              routeData.Values.Add("action", "HttpError404");
              break;
          case 500:
              // Server error.
              routeData.Values.Add("action", "HttpError500");
              break;

           // Here you can handle Views to other error codes.
           // I choose a General error template  
           default:
              routeData.Values.Add("action", "General");
              break;
      }
  }           

  // Pass exception details to the target error View.
  routeData.Values.Add("error", exception);

  // Clear the error on server.
  Server.ClearError();

  // Avoid IIS7 getting in the middle
  Response.TrySkipIisCustomErrors = true; 

  // Call target Controller and pass the routeData.
  IController errorController = new ErrorController();
  errorController.Execute(new RequestContext(    
       new HttpContextWrapper(Context), routeData));
}

404 요구 사항

다음은 404 솔루션에 대한 요구 사항이며 아래에서 구현 방법을 보여줍니다.

  • 나쁜 행동으로 일치하는 경로를 처리하고 싶습니다.
  • 불량 컨트롤러로 일치하는 경로를 처리하고 싶습니다.
  • 일치하지 않는 경로 (앱이 이해할 수없는 임의의 URL)를 처리하고 싶습니다 .Global.asax 또는 IIS까지 버블 링을 원하지 않습니다. 그러면 MVC 앱으로 올바르게 리디렉션 할 수 없기 때문입니다
  • 존재하지 않는 객체에 대해 ID를 제출할 때와 같이 위와 같은 방식으로 사용자 정의 404를 처리하는 방법을 원합니다.
  • 난 내가 이상 (필요한 경우 더 많은 데이터를 펌핑 할 수있는 할 수있는 MVC 뷰 (안 정적 페이지)를 돌려 내 모든 404을 원하는 좋은 404 개 디자인 ) 그들이 있어야 는 HTTP 404 상태 코드를 반환

해결책

Application_Error처리되지 않은 예외 및 로깅 ( Shay Jacoby의 답변와 같은)과 같은 더 높은 것들을 위해 Global.asax에 저장해야 하지만 404 처리는하지 않아야한다고 생각합니다 . 이것이 내 제안이 Global.asax 파일에서 404 항목을 유지하는 이유입니다.

1 단계 : 404 오류 논리의 공통 위치

이것은 유지 관리에 좋은 아이디어입니다. 잘 설계된 404 페이지의 향후 개선 사항을 쉽게 적용 할 수 있도록 ErrorController를 사용하십시오 . 또한 응답에 404 코드가 있는지 확인하십시오 !

public class ErrorController : MyController
{
    #region Http404

    public ActionResult Http404(string url)
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        var model = new NotFoundViewModel();
        // If the url is relative ('NotFound' route) then replace with Requested path
        model.RequestedUrl = Request.Url.OriginalString.Contains(url) & Request.Url.OriginalString != url ?
            Request.Url.OriginalString : url;
        // Dont get the user stuck in a 'retry loop' by
        // allowing the Referrer to be the same as the Request
        model.ReferrerUrl = Request.UrlReferrer != null &&
            Request.UrlReferrer.OriginalString != model.RequestedUrl ?
            Request.UrlReferrer.OriginalString : null;

        // TODO: insert ILogger here

        return View("NotFound", model);
    }
    public class NotFoundViewModel
    {
        public string RequestedUrl { get; set; }
        public string ReferrerUrl { get; set; }
    }

    #endregion
}

2 단계 : 기본 Controller 클래스를 사용하여 사용자 정의 404 조치를 쉽게 호출하고 연결하십시오. HandleUnknownAction

ASP.NET MVC의 404는 여러 곳에서 포착해야합니다. 첫 번째는 HandleUnknownAction입니다.

InvokeHttp404방법은 ErrorController새로운 Http404조치 로 다시 라우팅 할 수있는 공통된 장소를 만듭니다 . 건조를 생각하십시오 !

public abstract class MyController : Controller
{
    #region Http404 handling

    protected override void HandleUnknownAction(string actionName)
    {
        // If controller is ErrorController dont 'nest' exceptions
        if (this.GetType() != typeof(ErrorController))
            this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<ErrorController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Error");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

    #endregion
}

3 단계 : Controller Factory에서 Dependency Injection을 사용하고 404 HttpExceptions 연결

이와 같이 (StructureMap 일 필요는 없음) :

MVC1.0 예 :

public class StructureMapControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(RequestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }
}

MVC2.0 예 :

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType);
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == 404)
            {
                IController errorController = ObjectFactory.GetInstance<ErrorController>();
                ((ErrorController)errorController).InvokeHttp404(requestContext.HttpContext);

                return errorController;
            }
            else
                throw ex;
        }

        return ObjectFactory.GetInstance(controllerType) as Controller;
    }

오류가 발생한 위치에 더 가깝게 오류를 잡는 것이 좋습니다. 이것이 내가 Application_Error핸들러 보다 위의 것을 선호하는 이유 입니다.

이것은 404를 잡는 두 번째 장소입니다.

4 단계 : 앱으로 구문 분석되지 않은 URL에 대해 NotFound 경로를 Global.asax에 추가

이 경로는 우리의 Http404행동을 가리켜 야합니다 . 통지 url라우팅 엔진이 여기에 도메인 부분을 제거하기 때문에 PARAM 상대 URL 될 것인가? 이것이 우리가 1 단계에서 모든 조건부 URL 논리를 갖는 이유입니다.

        routes.MapRoute("NotFound", "{*url}", 
            new { controller = "Error", action = "Http404" });

MVC 앱에서 404를 잡을 수있는 세 번째이자 마지막 장소입니다. 여기서 일치하지 않는 경로를 찾지 못하면 MVC가 문제를 ASP.NET (Global.asax)으로 전달하므로이 상황에서는 실제로 원하지 않습니다.

5 단계 : 마지막으로 앱에서 무언가를 찾을 수 없을 때 404를 호출합니다.

잘못된 ID가 대출 컨트롤러에 제출 될 때와 같이 (에서 파생 됨 MyController) :

    //
    // GET: /Detail/ID

    public ActionResult Detail(int ID)
    {
        Loan loan = this._svc.GetLoans().WithID(ID);
        if (loan == null)
            return this.InvokeHttp404(HttpContext);
        else
            return View(loan);
    }

이 모든 것이 적은 코드로 적은 수의 장소에 연결될 수 있다면 좋을 것입니다.

지금까지 의견을 보내 주셔서 감사합니다. 더 많은 것을 얻고 싶습니다.

참고 : 이것은 원래의 답변에서 크게 편집되었지만 목적 / 요구 사항은 동일합니다-이것이 새로운 답변을 추가하지 않은 이유입니다


ASP.NET MVC는 사용자 지정 404 페이지를 잘 지원하지 않습니다. 맞춤형 컨트롤러 공장, 포괄 루트, 기본 컨트롤러 클래스 HandleUnknownAction-argh!

지금까지 IIS 사용자 정의 오류 페이지가 더 나은 대안입니다.

web.config

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

ErrorController

public class ErrorController : Controller
{
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        return View();
    }
}

샘플 프로젝트


빠른 답변 / TL; DR

여기에 이미지 설명을 입력하십시오

게으른 사람들을 위해 :

Install-Package MagicalUnicornMvcErrorToolkit -Version 1.0

그런 다음이 줄을 제거하십시오. global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

그리고 이것은 IIS7 + 및 IIS Express에만 해당됩니다.

Cassini를 사용하는 경우 .. 음 .. 어 .. 어색한 ... 어색한


길고 설명 된 답변

나는 이것이 대답되었다는 것을 안다. 그러나 그 대답은 정말 간단합니다 ( David FowlerDamian Edwards 에게 정말로 응답 해주었습니다).

사용자 정의 작업을 수행 할 필요없습니다 .

의 경우 ASP.NET MVC3모든 비트와 조각이 있습니다.

1 단계-> 2 개의 지점에서 web.config를 업데이트하십시오.

<system.web>
    <customErrors mode="On" defaultRedirect="/ServerError">
      <error statusCode="404" redirect="/NotFound" />
    </customErrors>

<system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404" subStatusCode="-1" />
      <error statusCode="404" path="/NotFound" responseMode="ExecuteURL" />
      <remove statusCode="500" subStatusCode="-1" />
      <error statusCode="500" path="/ServerError" responseMode="ExecuteURL" />
    </httpErrors>    

...
<system.webServer>
...
</system.web>

이제 사용하기로 결정한 경로를주의해서 기록하십시오. 당신은 아무것도 사용할 수 있지만 내 경로는

  • /NotFound <-404를 찾을 수 없으면 오류 페이지입니다.
  • /ServerError<-다른 오류의 경우 내 코드에서 발생하는 오류를 포함하십시오. 이것은 500 내부 서버 오류입니다

첫 번째 섹션에 하나의 사용자 정의 항목 <system.web>있는 방법을 참조하십시오 . 항목? (예 : 코드에 버그가 있고 사용자의 요청과 충돌 할 때 발생하는 성가신 오류)를 포함한 다른 모든 오류 때문에 하나의 상태 코드 만 나열했습니다 .. 다른 모든 오류는 설정에 의해 처리됩니다 . , 404 페이지를 찾을 수없는 경우 경로로 이동하십시오 .statusCode="404"500 Server ErrordefaultRedirect="/ServerError"/ServerError

확인. 그 길을 벗어났습니다 .. 지금 내 경로에 나열된global.asax

2 단계-Global.asax에서 경로 생성

여기 전체 경로 섹션이 있습니다.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.IgnoreRoute("{*favicon}", new {favicon = @"(.*/)?favicon.ico(/.*)?"});

    routes.MapRoute(
        "Error - 404",
        "NotFound",
        new { controller = "Error", action = "NotFound" }
        );

    routes.MapRoute(
        "Error - 500",
        "ServerError",
        new { controller = "Error", action = "ServerError"}
        );

    routes.MapRoute(
        "Default", // Route name
        "{controller}/{action}/{id}", // URL with parameters
        new {controller = "Home", action = "Index", id = UrlParameter.Optional}
        );
}

그것은 두 개의 무시 경로를 나열합니다-> axd'sfavicons(ooo! 보너스 무시 경로, 당신을 위해!) 그런 다음 (그리고 명령은 여기에서 명령입니다), 나는 두 가지 명시 적 오류 처리 경로를 가지고 있습니다. 이 경우 기본 설정입니다. 물론, 나는 더 많은 것을 가지고 있지만 그것은 내 웹 사이트에 특별합니다. 오류 경로가 목록의 맨 위에 있는지 확인하십시오. 순서는 필수적 입니다.

마지막으로 global.asax파일 내부에있는 동안 HandleError 특성을 전역 적으로 등록하지 않습니다. 아뇨, 아뇨 나다. 아니. 니엔 부정. 안돼 ...

이 줄을 제거하십시오 global.asax

GlobalFilters.Filters.Add(new HandleErrorAttribute());

3 단계-조치 방법으로 컨트롤러 작성

이제 .. 우리는 두 가지 행동 방법으로 컨트롤러를 추가합니다 ...

public class ErrorController : Controller
{
    public ActionResult NotFound()
    {
        Response.StatusCode = (int)HttpStatusCode.NotFound;
        return View();
    }

    public ActionResult ServerError()
    {
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        // Todo: Pass the exception into the view model, which you can make.
        //       That's an exercise, dear reader, for -you-.
        //       In case u want to pass it to the view, if you're admin, etc.
        // if (User.IsAdmin) // <-- I just made that up :) U get the idea...
        // {
        //     var exception = Server.GetLastError();
        //     // etc..
        // }

        return View();
    }

    // Shhh .. secret test method .. ooOOooOooOOOooohhhhhhhh
    public ActionResult ThrowError()
    {
        throw new NotImplementedException("Pew ^ Pew");
    }
}

좋아, 이것 좀 봐 우선, 여기 에는 속성 없습니다 [HandleError] . 왜? 내장 된 ASP.NET프레임 워크는 이미 오류를 처리하고 있으며 오류를 처리하기 위해 해야하는 모든 똥을 지정 했기 때문에 :)이 방법에 있습니다!

다음으로 두 가지 행동 방법이 있습니다. 거기에 힘든 것은 없습니다. 예외 정보를 표시하려면 Server.GetLastError()해당 정보를 얻는 데 사용할 수 있습니다 .

보너스 WTF : 예, 오류 처리를 테스트하기 위해 세 번째 조치 방법을 만들었습니다.

4 단계-보기 작성

마지막으로 두 개의 뷰를 만듭니다. 이 컨트롤러의 일반 시야에 em을 넣으십시오.

여기에 이미지 설명을 입력하십시오

보너스 코멘트

  • 당신은 필요하지 않습니다 Application_Error(object sender, EventArgs e)
  • 위의 단계는 모두 Elmah 와 100 % 완벽하게 작동 합니다. 엘마 프레이크 스 약!

그리고 그것은 내 친구들입니다.

자, 이것을 많이 읽은 것을 축하하고 유니콘을 상으로 삼았습니다!

여기에 이미지 설명을 입력하십시오


MVC (특히 MVC3) 에서 404를 올바르게 관리하는 방법에 대해 많은 것을 조사 했으며 IMHO는 내가 생각해 낸 최고의 솔루션입니다.

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

(선택 과목)

설명:

AFAIK에는 ASP.NET MVC3 앱이 404를 생성 할 수있는 6 가지 경우가 있습니다.

(ASP.NET Framework에서 자동 생성 :)

(1) URL이 라우팅 테이블에서 일치하는 것을 찾지 않습니다.

(ASP.NET MVC Framework에서 자동으로 생성됨)

(2) URL이 라우팅 테이블에서 일치하는 것을 찾지 만 존재하지 않는 컨트롤러를 지정합니다.

(3) URL이 라우팅 테이블에서 일치하는 것을 찾지 만 존재하지 않는 동작을 지정합니다.

(수동 생성 :)

(4) 액션은 HttpNotFound () 메소드를 사용하여 HttpNotFoundResult를 반환합니다.

(5) 액션은 상태 코드가 404 인 HttpException을 발생시킵니다.

(6) 작업은 Response.StatusCode 속성을 404로 수동으로 수정합니다.

일반적으로 3 가지 목표를 달성하려고합니다.

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

(2) 클라이언트 응답에 404 상태 코드를 유지하십시오 (특히 SEO에 중요 함).

(3) 302 리디렉션을 사용하지 않고 직접 응답을 보냅니다.

이를 달성하기 위해 여러 가지 방법이 있습니다.

(1)

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

이 솔루션의 문제점 :

  1. 경우 (1), (4), (6)의 경우 목표 (1)을 준수하지 않습니다.
  2. 목표 (2)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.
  3. 목표 (3)을 준수하지 않습니다.

(2)

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

이 솔루션의 문제점 :

  1. IIS 7 이상에서만 작동합니다.
  2. (2), (3), (5)의 경우 목표 (1)을 준수하지 않습니다.
  3. 목표 (2)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.

(삼)

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

이 솔루션의 문제점 :

  1. IIS 7 이상에서만 작동합니다.
  2. 목표 (2)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.
  3. 응용 프로그램 레벨 http 예외를 숨 깁니다. 예를 들어 customErrors 섹션, System.Web.Mvc.HandleErrorAttribute 등은 사용할 수 없습니다. 일반적인 오류 페이지 만 표시 할 수는 없습니다.

(4)

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

이 솔루션의 문제점 :

  1. IIS 7 이상에서만 작동합니다.
  2. 목표 (2)를 자동으로 준수하지 않습니다. 수동으로 프로그래밍해야합니다.
  3. (2), (3), (5)의 경우 목표 (3)을 준수하지 않습니다.

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


나는 cottsaks 솔루션을 정말 좋아하고 매우 명확하게 설명되어 있다고 생각합니다. 내 유일한 추가는 다음과 같이 2 단계를 변경하는 것이 었습니다

public abstract class MyController : Controller
{

    #region Http404 handling

    protected override void HandleUnknownAction(string actionName)
    {
        //if controller is ErrorController dont 'nest' exceptions
        if(this.GetType() != typeof(ErrorController))
        this.InvokeHttp404(HttpContext);
    }

    public ActionResult InvokeHttp404(HttpContextBase httpContext)
    {
        IController errorController = ObjectFactory.GetInstance<ErrorController>();
        var errorRoute = new RouteData();
        errorRoute.Values.Add("controller", "Error");
        errorRoute.Values.Add("action", "Http404");
        errorRoute.Values.Add("url", httpContext.Request.Url.OriginalString);
        errorController.Execute(new RequestContext(
             httpContext, errorRoute));

        return new EmptyResult();
    }

    #endregion
}

기본적으로 이는 유효하지 않은 조치 및 컨트롤러가 포함 된 URL이 예외 루틴을 두 번 트리거하지 못하게합니다. 예 : asdfsdf / dfgdfgd와 같은 URL의 경우


잘못된 컨트롤러에 대해 @cottsak의 메소드를 얻을 수있는 유일한 방법은 다음과 같이 CustomControllerFactory에서 기존 경로 요청을 수정하는 것입니다.

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        try
        {
            if (controllerType == null)
                return base.GetControllerInstance(requestContext, controllerType); 
            else
                return ObjectFactory.GetInstance(controllerType) as Controller;
        }
        catch (HttpException ex)
        {
            if (ex.GetHttpCode() == (int)HttpStatusCode.NotFound)
            {
                requestContext.RouteData.Values["controller"] = "Error";
                requestContext.RouteData.Values["action"] = "Http404";
                requestContext.RouteData.Values.Add("url", requestContext.HttpContext.Request.Url.OriginalString);

                return ObjectFactory.GetInstance<ErrorController>();
            }
            else
                throw ex;
        }
    }
}

MVC 2.0을 사용하고 있다고 언급해야합니다.


다음은 MVC 도구를 사용하여 잘못된 컨트롤러 이름, 잘못된 경로 이름 및 Action 메서드 내부에 적합한 다른 기준에 대한 요청을 처리 할 수있는 다른 방법입니다. 개인적으로 302 / 200 리디렉션을 수행 Server.Transfer하고 Razor보기를 사용하여 ResponseRewrite ( )를 지원하지 않기 때문에 가능한 많은 web.config 설정을 피하는 것이 좋습니다. SEO 이유로 커스텀 오류 페이지가있는 404를 반환하고 싶습니다.

이 중 일부는 위의 cottsak 기술을 새롭게 도입 한 것입니다.

이 솔루션은 대신 MVC 3 오류 필터를 선호하는 최소 web.config 설정을 사용합니다.

용법

액션이나 커스텀 ActionFilterAttribute에서 HttpException을 던지십시오.

Throw New HttpException(HttpStatusCode.NotFound, "[Custom Exception Message Here]")

1 단계

web.config에 다음 설정을 추가하십시오. MVC의 HandleErrorAttribute를 사용해야합니다.

<customErrors mode="On" redirectMode="ResponseRedirect" />

2 단계

HTTP 오류를 제외하고 MVC 프레임 워크의 HandleErrorAttribute와 유사한 사용자 정의 HandleHttpErrorAttribute를 추가하십시오.

<AttributeUsage(AttributeTargets.All, AllowMultiple:=True)>
Public Class HandleHttpErrorAttribute
    Inherits FilterAttribute
    Implements IExceptionFilter

    Private Const m_DefaultViewFormat As String = "ErrorHttp{0}"

    Private m_HttpCode As HttpStatusCode
    Private m_Master As String
    Private m_View As String

    Public Property HttpCode As HttpStatusCode
        Get
            If m_HttpCode = 0 Then
                Return HttpStatusCode.NotFound
            End If
            Return m_HttpCode
        End Get
        Set(value As HttpStatusCode)
            m_HttpCode = value
        End Set
    End Property

    Public Property Master As String
        Get
            Return If(m_Master, String.Empty)
        End Get
        Set(value As String)
            m_Master = value
        End Set
    End Property

    Public Property View As String
        Get
            If String.IsNullOrEmpty(m_View) Then
                Return String.Format(m_DefaultViewFormat, Me.HttpCode)
            End If
            Return m_View
        End Get
        Set(value As String)
            m_View = value
        End Set
    End Property

    Public Sub OnException(filterContext As System.Web.Mvc.ExceptionContext) Implements System.Web.Mvc.IExceptionFilter.OnException
        If filterContext Is Nothing Then Throw New ArgumentException("filterContext")

        If filterContext.IsChildAction Then
            Return
        End If

        If filterContext.ExceptionHandled OrElse Not filterContext.HttpContext.IsCustomErrorEnabled Then
            Return
        End If

        Dim ex As HttpException = TryCast(filterContext.Exception, HttpException)
        If ex Is Nothing OrElse ex.GetHttpCode = HttpStatusCode.InternalServerError Then
            Return
        End If

        If ex.GetHttpCode <> Me.HttpCode Then
            Return
        End If

        Dim controllerName As String = filterContext.RouteData.Values("controller")
        Dim actionName As String = filterContext.RouteData.Values("action")
        Dim model As New HandleErrorInfo(filterContext.Exception, controllerName, actionName)

        filterContext.Result = New ViewResult With {
            .ViewName = Me.View,
            .MasterName = Me.Master,
            .ViewData = New ViewDataDictionary(Of HandleErrorInfo)(model),
            .TempData = filterContext.Controller.TempData
        }
        filterContext.ExceptionHandled = True
        filterContext.HttpContext.Response.Clear()
        filterContext.HttpContext.Response.StatusCode = Me.HttpCode
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = True
    End Sub
End Class

3 단계

GlobalFilterCollection (에 필터를 추가 GlobalFilters.Filters에서) Global.asax. 이 예제는 모든 InternalServerError (500) 오류를 오류 공유보기 ( Views/Shared/Error.vbhtml)로 라우팅합니다 . NotFound (404) 오류는 공유보기에서도 ErrorHttp404.vbhtml로 전송됩니다. 여기에 401 오류를 추가하여 HTTP 오류 코드를 추가로 확장하는 방법을 보여줍니다. 이 뷰는 공유 뷰 여야하며 모두 System.Web.Mvc.HandleErrorInfo객체를 모델로 사용합니다 .

filters.Add(New HandleHttpErrorAttribute With {.View = "ErrorHttp401", .HttpCode = HttpStatusCode.Unauthorized})
filters.Add(New HandleHttpErrorAttribute With {.View = "ErrorHttp404", .HttpCode = HttpStatusCode.NotFound})
filters.Add(New HandleErrorAttribute With {.View = "Error"})

4 단계

기본 컨트롤러 클래스를 생성하고 컨트롤러에서 상속하십시오. 이 단계를 통해 알 수없는 동작 이름을 처리하고 HandleHttpErrorAttribute로 HTTP 404 오류를 발생시킬 수 있습니다.

Public Class BaseController
    Inherits System.Web.Mvc.Controller

    Protected Overrides Sub HandleUnknownAction(actionName As String)
        Me.ActionInvoker.InvokeAction(Me.ControllerContext, "Unknown")
    End Sub

    Public Function Unknown() As ActionResult
        Throw New HttpException(HttpStatusCode.NotFound, "The specified controller or action does not exist.")
        Return New EmptyResult
    End Function
End Class

5 단계

ControllerFactory 재정의를 만들고 Application_Start의 Global.asax 파일에서 재정의하십시오. 이 단계를 통해 유효하지 않은 컨트롤러 이름을 지정한 경우 HTTP 404 예외를 발생시킬 수 있습니다.

Public Class MyControllerFactory
    Inherits DefaultControllerFactory

    Protected Overrides Function GetControllerInstance(requestContext As System.Web.Routing.RequestContext, controllerType As System.Type) As System.Web.Mvc.IController
        Try
            Return MyBase.GetControllerInstance(requestContext, controllerType)
        Catch ex As HttpException
            Return DependencyResolver.Current.GetService(Of BaseController)()
        End Try
    End Function
End Class

'In Global.asax.vb Application_Start:

controllerBuilder.Current.SetControllerFactory(New MyControllerFactory)

6 단계

BaseController Unknown 액션에 대한 RoutTable.Routes에 특별한 경로를 포함시킵니다. 이것은 사용자가 알 수없는 컨트롤러 또는 알 수없는 동작에 액세스하는 경우 404를 올리는 데 도움이됩니다.

'BaseController
routes.MapRoute( _
    "Unknown", "BaseController/{action}/{id}", _
    New With {.controller = "BaseController", .action = "Unknown", .id = UrlParameter.Optional} _
)

요약

이 예제는 MVC 프레임 워크를 사용하여 필터 속성 및 공유 오류보기를 사용하여 경로 재지 정하지 않고 브라우저에 404 Http 오류 코드를 리턴하는 방법을 보여줍니다. 또한 유효하지 않은 제어기 이름과 조치 이름이 지정된 경우 동일한 사용자 정의 오류 페이지를 표시합니다.

유효하지 않은 컨트롤러 이름, 작업 이름 및 Home / TriggerNotFound 작업에서 발생하는 사용자 지정 404의 스크린 샷을 추가하여 하나를 게시 할 수있는 충분한 투표를 얻는 경우 =). 이 솔루션을 사용하여 다음 URL에 액세스하면 Fiddler가 404 메시지를 반환합니다.

/InvalidController
/Home/InvalidRoute
/InvalidController/InvalidRoute
/Home/TriggerNotFound

위의 cottsak의 게시물과 이러한 기사는 좋은 참고 자료였습니다.


처리되지 않은 영역, 컨트롤러 및 작업에서 작동하는 단축 솔루션 :

  1. 보기 404.cshtml을 작성하십시오.

  2. 컨트롤러의 기본 클래스를 작성하십시오.

    public class Controller : System.Web.Mvc.Controller
    {
        protected override void HandleUnknownAction(string actionName)
        {
            Http404().ExecuteResult(ControllerContext);
        }
    
        protected virtual ViewResult Http404()
        {
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            return View("404");
        }
    }
    
  3. 기본 컨트롤러를 폴백으로 반환하는 사용자 정의 컨트롤러 팩토리를 만듭니다.

    public class ControllerFactory : DefaultControllerFactory
    {
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            if (controllerType != null)
                return base.GetControllerInstance(requestContext, controllerType);
    
            return new Controller();
        }
    }
    
  4. Application_Start()다음 줄에 추가하십시오 .

    ControllerBuilder.Current.SetControllerFactory(typeof(ControllerFactory));
    

MVC4에서 WebAPI 404는 다음과 같은 방식으로 처리 할 수 ​​있습니다.

코스 APICONTROLLER

    // GET /api/courses/5
    public HttpResponseMessage<Courses> Get(int id)
    {
        HttpResponseMessage<Courses> resp = null;

        var aCourse = _courses.Where(c => c.Id == id).FirstOrDefault();

        resp = aCourse == null ? new HttpResponseMessage<Courses>(System.Net.HttpStatusCode.NotFound) : new HttpResponseMessage<Courses>(aCourse);

        return resp;
    }

가정 관제사

public ActionResult Course(int id)
{
    return View(id);
}

전망

<div id="course"></div>
<script type="text/javascript">
    var id = @Model;
    var course = $('#course');
    $.ajax({    
        url: '/api/courses/' + id,
        success: function (data) {
            course.text(data.Name);
        },
        statusCode: {
            404: function() 
            {
                course.text('Course not available!');    
            }
        }
    });
</script>

글로벌

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

결과

여기에 이미지 설명을 입력하십시오


너겟에서 NotFoundMVC를 사용해보십시오. 작동하지만 설정이 없습니다.


누군가가 유용하다고 생각하는 경우 내 솔루션.

Web.config에서 :

<system.web>
    <customErrors mode="On" defaultRedirect="Error" >
      <error statusCode="404" redirect="~/Error/PageNotFound"/>
    </customErrors>
    ...
</system.web>

에서 Controllers/ErrorController.cs:

public class ErrorController : Controller
{
    public ActionResult PageNotFound()
    {
        if(Request.IsAjaxRequest()) {
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            return Content("Not Found", "text/plain");
        }

        return View();
    }
}

폴더에를 추가하면 PageNotFound.cshtml됩니다 Shared.


그러나 내부 구성 이 MVC와 호환되지 않는 때문에 표준 CustomErrors구성 이 제대로 작동Server.Transfer 하는 것 같습니다 ResponseRewrite.

이것은 나에게 눈에 띄는 기능 구멍처럼 느껴지므로 HTTP 모듈을 사용 하여이 기능을 다시 구현하기로 결정했습니다. 아래 솔루션을 사용하면 평소처럼 유효한 MVC 경로로 리디렉션하여 모든 HTTP 상태 코드 (404 포함)를 처리 할 수 ​​있습니다.

<customErrors mode="RemoteOnly" redirectMode="ResponseRewrite">
    <error statusCode="404" redirect="404.aspx" />
    <error statusCode="500" redirect="~/MVCErrorPage" />
</customErrors>

이것은 다음 플랫폼에서 테스트되었습니다.

  • 통합 파이프 라인 모드의 MVC4 (IIS Express 8)
  • 클래식 모드의 MVC4 (VS Development Server, Cassini)
  • 클래식 모드의 MVC4 (IIS6)

혜택

  • 모든 MVC 프로젝트에 적용 할 수있는 일반 솔루션
  • 전통적인 사용자 정의 오류 구성 지원
  • 통합 파이프 라인 및 클래식 모드에서 작동

해결책

namespace Foo.Bar.Modules {

    /// <summary>
    /// Enables support for CustomErrors ResponseRewrite mode in MVC.
    /// </summary>
    public class ErrorHandler : IHttpModule {

        private HttpContext HttpContext { get { return HttpContext.Current; } }
        private CustomErrorsSection CustomErrors { get; set; }

        public void Init(HttpApplication application) {
            System.Configuration.Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~");
            CustomErrors = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");

            application.EndRequest += Application_EndRequest;
        }

        protected void Application_EndRequest(object sender, EventArgs e) {

            // only handle rewrite mode, ignore redirect configuration (if it ain't broke don't re-implement it)
            if (CustomErrors.RedirectMode == CustomErrorsRedirectMode.ResponseRewrite && HttpContext.IsCustomErrorEnabled) {

                int statusCode = HttpContext.Response.StatusCode;

                // if this request has thrown an exception then find the real status code
                Exception exception = HttpContext.Error;
                if (exception != null) {
                    // set default error status code for application exceptions
                    statusCode = (int)HttpStatusCode.InternalServerError;
                }

                HttpException httpException = exception as HttpException;
                if (httpException != null) {
                    statusCode = httpException.GetHttpCode();
                }

                if ((HttpStatusCode)statusCode != HttpStatusCode.OK) {

                    Dictionary<int, string> errorPaths = new Dictionary<int, string>();

                    foreach (CustomError error in CustomErrors.Errors) {
                        errorPaths.Add(error.StatusCode, error.Redirect);
                    }

                    // find a custom error path for this status code
                    if (errorPaths.Keys.Contains(statusCode)) {
                        string url = errorPaths[statusCode];

                        // avoid circular redirects
                        if (!HttpContext.Request.Url.AbsolutePath.Equals(VirtualPathUtility.ToAbsolute(url))) {

                            HttpContext.Response.Clear();
                            HttpContext.Response.TrySkipIisCustomErrors = true;

                            HttpContext.Server.ClearError();

                            // do the redirect here
                            if (HttpRuntime.UsingIntegratedPipeline) {
                                HttpContext.Server.TransferRequest(url, true);
                            }
                            else {
                                HttpContext.RewritePath(url, false);

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

                            // return the original status code to the client
                            // (this won't work in integrated pipleline mode)
                            HttpContext.Response.StatusCode = statusCode;

                        }
                    }

                }

            }

        }

        public void Dispose() {

        }


    }

}

용법

이것을 web.config의 최종 HTTP 모듈로 포함

  <system.web>
    <httpModules>
      <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
    </httpModules>
  </system.web>

  <!-- IIS7+ -->
  <system.webServer>
    <modules>
      <add name="ErrorHandler" type="Foo.Bar.Modules.ErrorHandler" />
    </modules>
  </system.webServer>

주의를 기울이는 사람들에게는 통합 파이프 라인 모드에서 Server.TransferRequest작동 방식으로 인해 항상 HTTP 200으로 응답한다는 것을 알 수 있습니다. 올바른 오류 코드를 반환하려면 다음 오류 컨트롤러를 사용하십시오.

public class ErrorController : Controller {

    public ErrorController() { }

    public ActionResult Index(int id) {
        // pass real error code to client
        HttpContext.Response.StatusCode = id;
        HttpContext.Response.TrySkipIisCustomErrors = true;

        return View("Errors/" + id.ToString());
    }

}

ASP.NET MVC의 오류를 다루는 것은 엉덩이에 고통입니다. 이 페이지와 다른 질문과 사이트에서 많은 제안을 시도했지만 아무런 효과가 없습니다. 한 가지 제안은 system.webserver 내의 web.config에서 오류를 처리하는 것이지만 빈 페이지반환합니다 .

이 솔루션을 만들 때 나의 목표는;

  • 리디렉션하지 않음
  • 기본 오류 처리와 같이 200 / Ok가 아닌 적절한 상태 코드 반환

여기 내 해결책이 있습니다.

1. system.web 섹션에 다음을 추가 하십시오.

   <system.web>
     <customErrors mode="On" redirectMode="ResponseRewrite">
      <error statusCode="404"  redirect="~/Error/404.aspx" />
      <error statusCode="500" redirect="~/Error/500.aspx" />
     </customErrors>
    <system.web>

위의 경우 routes.config 에서 처리 하지 않은 URL 과 처리되지 않은 예외, 특히 뷰에서 발생하는 예외를 처리합니다. html이 아닌 aspx를 사용했습니다 . 코드 뒤에 응답 코드추가 할 수 있습니다 .

2 . 프로젝트의 루트에 Error (또는 원하는 것) 라는 폴더를 작성 하고 두 개의 웹 양식을 추가하십시오. 아래는 내 404 페이지입니다.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="404.aspx.cs" Inherits="Myapp.Error._404" %>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title >Page Not found</title>
    <link href="<%=ResolveUrl("~/Content/myapp.css")%>" rel="stylesheet" />
</head>
<body>
    <div class="top-nav">
      <a runat="server" class="company-logo" href="~/"></a>
    </div>
    <div>
        <h1>404 - Page Not found</h1>
        <p>The page you are looking for cannot be found.</p>
        <hr />
        <footer></footer>
    </div>
</body>
</html>

코드 뒤에는 응답 코드를 설정했습니다.

protected void Page_Load(object sender, EventArgs e)
{
    Response.StatusCode = 404;
}

500 페이지에 대해서도 동일하게 수행

3. 컨트롤러 내의 오류를 처리합니다. 여러 가지 방법이 있습니다. 이것이 나를 위해 일한 것입니다. 모든 컨트롤러는 기본 컨트롤러에서 상속됩니다. 기본 컨트롤러에는 다음과 같은 방법이 있습니다

protected ActionResult ShowNotFound()
{
    return ShowNotFound("Page not found....");
}

protected ActionResult ShowNotFound(string message)
{
    return ShowCustomError(HttpStatusCode.NotFound, message);
}

protected ActionResult ShowServerError()
{
    return ShowServerError("Application error....");
}

protected ActionResult ShowServerError(string message)
{
    return ShowCustomError(HttpStatusCode.InternalServerError, message);
}

protected ActionResult ShowNotAuthorized()
{
    return ShowNotAuthorized("You are not allowed ....");

}

protected ActionResult ShowNotAuthorized(string message)
{
    return ShowCustomError(HttpStatusCode.Forbidden, message);
}

protected ActionResult ShowCustomError(HttpStatusCode statusCode, string message)
{
    Response.StatusCode = (int)statusCode;
    string title = "";
    switch (statusCode)
    {
        case HttpStatusCode.NotFound:
            title = "404 - Not found";
            break;
        case HttpStatusCode.Forbidden:
            title = "403 - Access Denied";
            break;
        default:
            title = "500 - Application Error";
            break;
    }
    ViewBag.Title = title;
    ViewBag.Message = message;
    return View("CustomError");
}

4. CustomError.cshtml을 공유 보기 폴더에 추가하십시오. 아래는 내 것입니다.

<h1>@ViewBag.Title</h1>
<br />
<p>@ViewBag.Message</p>

이제 애플리케이션 컨트롤러에서 다음과 같은 작업을 수행 할 수 있습니다.

public class WidgetsController : ControllerBase
{
  [HttpGet]
  public ActionResult Edit(int id)
  {
    Try
    {
       var widget = db.getWidgetById(id);
       if(widget == null)
          return ShowNotFound();
          //or return ShowNotFound("Invalid widget!");
       return View(widget);
    }
    catch(Exception ex)
    {
       //log error
       logger.Error(ex)
       return ShowServerError();
    }
  }
}

이제 경고를 위해 . 정적 파일 오류를 처리하지 않습니다. 따라서 example.com/widgets같은 경로가 있고 사용자가 example.com/widgets.html로 변경 하면 IIS 기본 오류 페이지가 표시되므로 다른 방법으로 IIS 수준 오류를 처리해야합니다.


내 의견이 너무 길어서 답변을 게시하는 중 ...

유니콘 포스트 / 답변에 대한 의견과 질문입니다.

https://stackoverflow.com/a/7499406/687549

나는이 대답이 다른 사람들보다 간단하다는 점과 Microsoft의 일부 사람들이 분명히 상담했다는 사실을 선호합니다. 그러나 세 가지 질문이 있으며 응답 할 수 있으면 ASP.NET MVC (x) 앱의 웹에서 404/500 오류 답변의 성배라고 부릅니다.

@ Pure.Krome

  1. 당신이 코멘트에서 SEO 물건과 답변을 업데이트 할 수 GWB에 의해 지적 (이 답변이의 대한 언급 결코) - <customErrors mode="On" redirectMode="ResponseRewrite"><httpErrors errorMode="Custom" existingResponse="Replace">?

  2. 그런 식으로 그것을 할 괜찮 경우 당신은 당신의 ASP.NET 팀 친구를 요구하지 수 - 좋은 것 몇 가지 확인을 가지고 - 어쩌면 큰 변화에 더 노 없습니다 redirectModeexistingResponseSEO 멋지게 연주 할 수 있도록 이런 식으로?!

  3. 당신은 모든 물건을 둘러싼 몇 가지 설명을 추가 할 수 있습니다 ( customErrors redirectMode="ResponseRewrite", customErrors redirectMode="ResponseRedirect", httpErrors errorMode="Custom" existingResponse="Replace", REMOVE customErrors누군가가 제안 완전하게 같은) 마이크로 소프트 친구에게 이야기 한 후?

내가 말하고 있었을 때; 54 000+ 조회수를 가진 상당히 인기있는 질문 인 것처럼 답변을보다 완벽하게 만들 수 있다면 좋을 것입니다.

업데이트 : 유니콘 답변은 302 Found와 200 OK를 수행하며 경로를 사용하여 404 만 반환하도록 변경할 수 없습니다. MVC : ish가 아닌 실제 파일이어야합니다. 다른 솔루션으로 넘어갑니다. 이것이 지금까지 궁극적 인 MVC : ish 답변으로 보였기 때문에 너무 나쁩니다.


허먼 칸의 솔루션과 거의 동일한 솔루션을 작은 주름으로 추가하면 프로젝트에 사용할 수 있습니다.

사용자 정의 오류 컨트롤러를 작성하십시오.

public class Error404Controller : BaseController
{
    [HttpGet]
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;
        return View("404");
    }
}

그런 다음 사용자 정의 컨트롤러 팩토리를 작성하십시오.

public class CustomControllerFactory : DefaultControllerFactory
{
    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        return controllerType == null ? new Error404Controller() : base.GetControllerInstance(requestContext, controllerType);
    }
}

마지막으로 사용자 정의 오류 컨트롤러에 재정의를 추가하십시오.

protected override void HandleUnknownAction(string actionName)
{
    var errorRoute = new RouteData();
    errorRoute.Values.Add("controller", "Error404");
    errorRoute.Values.Add("action", "PageNotFound");
    new Error404Controller().Execute(new RequestContext(HttpContext, errorRoute));
}

그리고 그게 다야. Web.config를 변경할 필요가 없습니다.


1) 추상 컨트롤러 클래스를 만듭니다.

public abstract class MyController:Controller
{
    public ActionResult NotFound()
    {
        Response.StatusCode = 404;
        return View("NotFound");
    }

    protected override void HandleUnknownAction(string actionName)
    {
        this.ActionInvoker.InvokeAction(this.ControllerContext, "NotFound");
    }
    protected override void OnAuthorization(AuthorizationContext filterContext) { }
}  

2) 모든 컨트롤러 에서이 추상 클래스에서 상속하십시오.

public class HomeController : MyController
{}  

3) 그리고 View-Shared 폴더에 "NotFound"라는보기를 추가하십시오.


이 스레드에 게시 된 대부분의 솔루션을 살펴 보았습니다. 이 질문은 오래되었지만 지금도 여전히 새로운 프로젝트에 적용 가능하므로 여기에 제시된 답변뿐만 아니라 다른 곳에서 많은 시간을 보냈습니다.

@Marco가 404가 발생할 수있는 여러 가지 사례를 지적했듯이, 나는 그 목록에 대해 함께 컴파일 한 솔루션을 확인했습니다. 그의 요구 사항 목록 외에도 하나 더 추가했습니다.

  • The solution should be able to handle MVC as well as AJAX/WebAPI calls in the most appropriate manner. (i.e. if 404 happens in MVC, it should show the Not Found page and if 404 happens in WebAPI, it should not hijack the XML/JSON response so that the consuming Javascript can parse it easily).

This solution is 2 fold:

First part of it comes from @Guillaume at https://stackoverflow.com/a/27354140/2310818. Their solution takes care of any 404 that were caused due to invalid route, invalid controller and invalid action.

The idea is to create a WebForm and then make it call the NotFound action of your MVC Errors Controller. It does all of this without any redirect so you will not see a single 302 in Fiddler. The original URL is also preserved, which makes this solution fantastic!


Second part of it comes from @Germán at https://stackoverflow.com/a/5536676/2310818. Their solution takes care of any 404 returned by your actions in the form of HttpNotFoundResult() or throw new HttpException()!

The idea is to have a filter look at the response as well as the exception thrown by your MVC controllers and to call the appropriate action in your Errors Controller. Again this solution works without any redirect and the original url is preserved!


As you can see, both of these solutions together offer a very robust error handling mechanism and they achieve all the requirements listed by @Marco as well as my requirements. If you would like to see a working sample or a demo of this solution, please leave in the comments and I would be happy to put it together.


모든 기사를 살펴 보았지만 아무것도 효과가 없습니다. 내 요구 사항 사용자가 URL 사용자 정의 404 페이지에 표시해야 할 내용이 매우 간단하다고 생각했지만 404의 처리를 올바르게 이해해야합니다.

 <system.web>
    <customErrors mode="On" redirectMode="ResponseRewrite">
      <error statusCode="404" redirect="~/PageNotFound.aspx"/>
    </customErrors>
  </system.web>
<system.webServer>
    <httpErrors errorMode="Custom">
      <remove statusCode="404"/>
      <error statusCode="404" path="/PageNotFound.html" responseMode="ExecuteURL"/>
    </httpErrors>
</system.webServer>

이 기사가 매우 유용하다는 것을 알았습니다. 한 번에 읽어야합니다. 손님 오류 페이지 벤 포스터

참고 URL : https://stackoverflow.com/questions/619895/how-can-i-properly-handle-404-in-asp-net-mvc



반응형