ASP.NET Custom 404가 404 Not Found 대신 200 OK를 반환 함


80

내 사이트에서 Google 웹 마스터 도구를 설정하려고 시도한 후 내 사용자 지정 ASP.NET 404 페이지가 404 상태 코드를 반환하지 않는 것을 발견했습니다. 올바른 사용자 정의 페이지를 표시하고 모든 것이 정상이라고 브라우저에 알 렸습니다. 이것은 soft 404 또는 false 404로 간주됩니다. Google은 이것을 좋아하지 않습니다. 그래서 문제에 대한 많은 기사를 찾았지만 원하는 솔루션이 작동하지 않는 것 같습니다.

내가 작업하고 싶은 해결책은 사용자 지정 404 페이지의 Page_Load 메서드 뒤에있는 코드에 다음 두 줄을 추가하는 것입니다.

Response.Status = "404 Not Found";
Response.StatusCode = 404;

이것은 작동하지 않습니다. 페이지는 여전히 200 OK를 반환합니다. 그러나 다음 코드를 디자인 코드에 하드 코딩하면 제대로 작동한다는 것을 알았습니다.

<asp:Content ID="ContentMain" ContentPlaceHolderID="ContentPlaceHolderMaster" runat="server">

<%
    Response.Status = "404 Not Found";
    Response.StatusCode = 404;
%>

 ... Much more code ...

</asp:content>

페이지가 마스터 페이지를 사용하고 있습니다. 그리고 내 web.config에서 사용자 지정 오류 페이지를 구성하고 있습니다. 나는 정말로 차라리 코드 뒤에 옵션을 사용하고 싶지만 디자인 / 레이아웃에 해킹 인라인 코드를 넣지 않고는 작동하지 않는 것 같습니다.


브라우저 상태는 무엇입니까? Firefox 용 애드온 Header Spy를 사용합니다.
Bobby Cannon

헤더 스파이 응답 : HTTP / 1.1 404 찾을 수 없음 날짜 : 2008 년
Ryan Cook

마스터 페이지를 사용하고 있습니까? 그게 다일 수도 있습니다. 마스터 페이지를 사용하지 않고 페이지를 시도해 보겠습니다 ...
Bobby Cannon

아니요.하지만 빠른 확인도 할 수 있습니다. 한 번 시도해 보겠습니다.
Ryan Cook

그래, 그게 다야! 마스터 페이지는 200 OK를 발생
Ryan Cook

답변:


72

해결책:

문제는 마스터 페이지의 사용이었습니다. 페이지 수명주기 후반에 상태 코드를 설정하여 작동하도록했습니다. 분명히 마스터 페이지의 렌더링이이를 재설정했기 때문에 렌더링 메서드를 무시하고 렌더링이 완료된 후에 설정했습니다.

protected override void Render(HtmlTextWriter writer)
{
    base.Render(writer);
    Response.StatusCode = 404;
}

마스터 페이지가 상태를 설정하는시기를 정확히 알기 위해 더 많은 작업을 수행 할 수 있지만, 그 상태는 귀하에게 맡기겠습니다.


원본 게시물 :

테스트 웹 앱이 제대로 작동하도록 할 수 있었는데, 적어도 사용자 지정 오류 페이지를 표시하고 404 상태 코드를 반환했습니다. 앱에 어떤 문제가 있는지 말씀 드릴 수는 없지만 내가 한 일은 말할 수 있습니다.

1) 사용자 지정 오류에 대한 web.config 편집 :

<customErrors mode="On">
  <error statusCode="404" redirect="404.aspx"/>
</customErrors>

2) 404.aspx 페이지를 추가하고 상태 코드를 404로 설정했습니다.

public partial class _04 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.StatusCode = 404;
    }
}

그게 다입니다. Asp.Net에 의해 처리되고 존재하지 않는 페이지 확장으로 이동하면 내 피들러 로그에 404가 명확하게 표시되며 다음은 헤더입니다.

HTTP/1.1 404 Not Found
Server: Microsoft-IIS/5.1
Date: Sun, 07 Dec 2008 06:04:13 GMT
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: text/html; charset=utf-8
Content-Length: 533

이제 htm 파일과 같이 Asp.Net에서 처리되지 않는 페이지로 이동하면 사용자 지정 페이지가 표시되지 않고 IIS에서 구성된 404가 표시됩니다.

다음은 귀하와 귀하의 문제에 도움이 될 수있는 더 자세한 정보를 담고있는 게시물입니다. 내 테스트는 새 페이지로 리디렉션을 수행하므로 요청 된 파일의 URL이 거의 손실됩니다 (쿼리 문자열 제외). .

Google 404 및 .NET 사용자 지정 오류 페이지

헤더 스파이 응답 :

HTTP/1.1 404 Not Found
Date: Sun, 07 Dec 2008 06:21:20 GMT

4
Header SpyFirefox 용
Kiquenet 2015 년

정적 .html사용자 정의 오류 페이지 에서는 어떻게 작동 합니까?
ebyrob

28

비슷한 문제가 발생하여 사용자 지정 페이지를 404 (ASPX)로 표시하고 로컬 호스트에서 제대로 작동했지만 원격 방문자가 연결하자마자 일반 IIS 404를 얻습니다.

이에 대한 해결책은

Response.TrySkipIisCustomErrors = true;

Response.StatusCode를 변경하기 전에.

Rick Strahl http://www.west-wind.com/weblog/posts/745738.aspx 를 통해 찾았습니다 .


12

IIS 7 솔루션은 web.config 파일에 다음을 추가하는 것입니다.

<system.webServer>
  <httpErrors existingResponse="Replace">
    <remove statusCode="500" subStatusCode="-1" />
    <remove statusCode="404" subStatusCode="-1" />
    <error statusCode="404" prefixLanguageFilePath="" path="404.htm" responseMode="File" />
    <error statusCode="500" prefixLanguageFilePath="" path="500.htm" responseMode="File" />
  </httpErrors>
</system.webServer>

http://forums.asp.net/t/1563128.aspx/1


3
나를 위해 일했습니다! 여기에서 작동하는 유일한 솔루션은 아마도 여러분이 언급 한 버전 때문일 것입니다 ...주의 :이 솔루션에서는 정적 .htm 파일 만 사용할 수 있습니다.
squarecandy

11

렌더링을 건너 뛰려면 Response.End ()를 호출 해보십시오 ...

Response.Status = "404 Not Found";
Response.StatusCode = 404;
Response.End();
return;

9

많은 테스트와 문제 해결 후 특정 호스팅 공급자가 반환 코드를 방해 할 수있는 것으로 보입니다. 콘텐츠에 "해킹"을 적용하여이 문제를 해결할 수있었습니다.

<%
// This code is required for host that do special 404 handling...
Response.Status = "404 Not Found";
Response.StatusCode = 404;
%>

이렇게하면 페이지가 무엇이든지 올바른 반환 코드를 반환 할 수 있습니다.


1

.NET 3.5를 사용하는 asp.net 웹 양식에서 다음 설정을 사용하여이 문제를 해결할 수있었습니다.

내가 구현 한 패턴은 헤더에 올바른 HTTP 상태 코드를 사용하여 모든 시나리오를 처리하도록 직접 작성했기 때문에 web.config에서 .NET의 사용자 지정 리디렉션 솔루션을 우회합니다.

먼저 web.config의 customErrors 섹션은 다음과 같습니다.

<customErrors mode="RemoteOnly" defaultRedirect="~/error.htm" />

이 설정은 CustomErrors 모드가 on으로 설정되어 있는지 확인하고, 이는 나중에 필요로하는 설정이며 error.htm의 defaultRedirect에 대한 all-else-fails 옵션을 제공합니다. 이것은 특정 오류에 대한 처리기가 없거나 끊어진 데이터베이스 연결 라인을 따라 무언가가있을 때 유용합니다.

둘째, 다음은 전역 asax 오류 이벤트입니다.

protected void Application_Error(object sender, EventArgs e)
    {
       HandleError();
    }

    private void HandleError()
    {
        var exception = Server.GetLastError();
        if (exception == null) return;

        var baseException = exception.GetBaseException();

        bool errorHandled = _applicationErrorHandler.HandleError(baseException);
        if (!errorHandled) return;


        var lastError = Server.GetLastError();
    if (null != lastError && HttpContext.Current.IsCustomErrorEnabled)
    {
        Elmah.ErrorSignal.FromCurrentContext().Raise(lastError.GetBaseException());
        Server.ClearError();
    }
    }

이 코드는 오류 처리 책임을 다른 클래스로 넘깁니다. 오류가 처리되지 않고 CustomErrors가 켜져 있으면 프로덕션 단계에서 오류가 처리되지 않은 경우가 있음을 의미합니다. 사용자가 볼 수 없도록 여기에서 지우지 만 Elmah에 로그인하여 무슨 일이 일어나고 있는지 알 수 있습니다.

applicationErrorHandler 클래스는 다음과 같습니다.

public bool HandleError(Exception exception)
        {
            if (exception == null) return false;

            var baseException = exception.GetBaseException();

            Elmah.ErrorSignal.FromCurrentContext().Raise(baseException);

            if (!HttpContext.Current.IsCustomErrorEnabled) return false;

            try
            {

                var behavior = _responseBehaviorFactory.GetBehavior(exception);
                if (behavior != null)
                {
                    behavior.ExecuteRedirect();
                    return true;
                }
            }
            catch (Exception ex)
            {
                Elmah.ErrorSignal.FromCurrentContext().Raise(ex);
            }
            return false;
        }

이 클래스는 기본적으로 명령 패턴을 사용하여 발생한 오류 유형에 적합한 오류 처리기를 찾습니다. 이 수준에서 Exception.GetBaseException ()을 사용하는 것이 중요합니다. 거의 모든 오류가 상위 수준 예외로 래핑되기 때문입니다. 예를 들어 aspx 페이지에서 "throw new System.Exception ()"을 수행하면이 수준에서 System.Exception이 아닌 HttpUnhandledException이 수신됩니다.

"공장"코드는 간단하며 다음과 같습니다.

public ResponseBehaviorFactory()
    {
        _behaviors = new Dictionary<Type, Func<IResponseBehavior>>
                        {
                            {typeof(StoreException), () => new Found302StoreResponseBehavior()},
                            {typeof(HttpUnhandledException), () => new HttpExceptionResponseBehavior()},
                            {typeof(HttpException), () => new HttpExceptionResponseBehavior()},
                            {typeof(Exception), () => new Found302DefaultResponseBehavior()}
                        };
    }

    public IResponseBehavior GetBehavior(Exception exception)
    {                                                                               
        if (exception == null) throw new ArgumentNullException("exception");

        Func<IResponseBehavior> behavior;
        bool tryGetValue = _behaviors.TryGetValue(exception.GetType(), out behavior);

        //default value here:
        if (!tryGetValue)
            _behaviors.TryGetValue(typeof(Exception), out behavior);

        if (behavior == null)
            Elmah.ErrorSignal.FromCurrentContext().Raise(
                new Exception(
                    "Danger! No Behavior defined for this Exception, therefore the user might have received a yellow screen of death!",
                    exception));
        return behavior();
    }

결국 확장 가능한 오류 처리 체계 설정이 있습니다. 정의 된 각 "동작"에는 오류 유형에 대한 사용자 지정 구현이 있습니다. 예를 들어, Http 예외는 상태 코드에 대해 검사되고 적절하게 처리됩니다. 404 상태 코드에는 Request.Redirect 대신 Server.Transfer가 헤더에 작성된 적절한 상태 코드와 함께 필요합니다.

도움이 되었기를 바랍니다.


0

아래 코드를 사용할 수 있습니다.

 Response.TrySkipIisCustomErrors = True
 Response.Status = "404 Not Found"
 Response.AddHeader("Location", "{your-path-to-your-404-page}")
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.