web-dev-qa-db-ja.com

404 Not Foundの代わりに200 OKを返すASP.NETカスタム404

Google Webmaster Tools用にサイトをセットアップしようとした後、カスタムASP.NET 404ページが404ステータスコードを返さないことがわかりました。正しいカスタムページを表示し、すべてが問題ないことをブラウザに伝えました。これはソフト404または偽404と見なされます。Googleはこれを好みません。そのため、この問題に関する多くの記事を見つけましたが、私が望む解決策はうまくいかないようでした。

私が働きたい解決策は、カスタム404ページのPage_Loadメソッドの背後にあるコードに次の2行を追加することです。

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でカスタムエラーページを構成しています。私は本当にコードビハインドオプションを使用しますが、デザイン/レイアウトにハックインラインコードを配置せずに機能させることはできません。

77
Bobby Cannon

解決策:

問題は、マスターページの使用であることが判明しました。ページのライフサイクルの後半でステータスコードを設定することで機能するようになりました。明らかにマスターページのレンダリングはリセットされていたので、renderメソッドをオーバーライドして、レンダリングの完了後に設定しました。

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

マスターページがいつステータスを設定しているかを正確に確認するために、さらに作業を行うことができますが、それはあなたにお任せします。


元の投稿:

テストWebアプリを正常に動作させることができました。少なくともカスタムエラーページが表示され、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
71
Ryan Cook

同様の問題があり、カスタムページを404(ASPX)として表示したいのですが、localhostで正常に機能しましたが、リモートの訪問者が接続するとすぐに一般的なIIS 404 。

これに対する解決策は、追加することでした

Response.TrySkipIisCustomErrors = true;

Response.StatusCodeを変更する前。

Rick Strahl経由で発見 http://www.west-wind.com/weblog/posts/745738.aspx

27
gary

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

12
Nick D

Response.End()を呼び出してレンダリングをスキップしてください...

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

多くのテストとトラブルシューティングの結果、特定のホスティングプロバイダーがリターンコードに干渉する可能性があるようです。コンテンツに「ハック」を適用することでこれを回避できました。

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

これにより、ページは何があっても正しいリターンコードを返すことができます。

7
Bobby Cannon

.NET 3.5を使用するasp.net Webフォームで次のセットアップを使用することで、この問題を回避できました。

私が実装したパターンは、web.configで.NETのカスタムリダイレクトソリューションをバイパスします。これは、ヘッダーに正しいHTTPステータスコードを持つすべてのシナリオを処理するために独自のコードを作成したためです。

まず、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が必要です。

お役に立てれば。

1
letsgetsilly