ASP.NETカスタム404が404ではなく200OKを返すが見つかりません


80

Googleウェブマスターツール用にサイトを設定しようとしたところ、カスタムASP.NET404ページが404ステータスコードを返さないことがわかりました。正しいカスタムページが表示され、ブラウザにすべて問題がないことが通知されました。これはソフト404またはフォールス404と見なされます。Googleはこれを好みません。そのため、この問題に関する記事をたくさん見つけましたが、私が望む解決策はうまくいかなかったようです。

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

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

これは機能しません。ページはまだ200OKを返します。ただし、次のコードをデザインコードにハードコーディングすると、正しく機能することがわかりました。

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

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

 ... Much more code ...

</asp:content>

ページはマスターページを使用しています。そして、web.configでカスタムエラーページを構成しています。私は実際にはコードビハインドオプションを使用したいのですが、デザイン/レイアウトにハックインラインコードを配置せずにそれを機能させることはできないようです。


ブラウザの状態は何ですか?Firefox用のアドオンヘッダースパイを使用しています。
ボビーキャノン

ヘッダースパイ応答:HTTP / 1.1 404見つかりません日付:2008年
ライアンクック

マスターページを使用していますか?多分それだけです。私は...マスターページを使用せずにページを尽くす
ボビー・キャノン

いいえ、そうではありませんでしたが、簡単なチェックもできます。試してみます。
ライアンクック

うん、それだけだ!マスターページは200OKを引き起こしました
Ryan Cook

回答:


72

解決:

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

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はほとんど失われます(クエリ文字列内を除く) 。

Google404および.NETカスタムエラーページ

ヘッダースパイ応答:

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

4
ヘッダースパイFirefox用の
Kiquenet 2015

これは静的な.htmlカスタムエラーページに対してどのように機能しますか?
ebyrob 2017年

28

カスタムページを404(ASPX)として表示したいという同様の問題があり、ローカルホストでは正常に機能しましたが、リモートの訪問者が接続するとすぐに汎用IIS404を取得しました。

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

Response.TrySkipIisCustomErrors = true;

Response.StatusCodeを変更する前。

RickStrahl経由で見つかりました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 2012

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

.NET3.5を使用するasp.netWebフォームで次の設定を使用することで、この問題を回避することができました。

私が実装したパターンは、ヘッダーに正しい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ページから「thrownew 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.