5

私のASP.NETMVCアプリケーションでは、HTTP500を返すとともに表示される一般的なエラーページが必要です。StackOverflowのこのページのようなものです。

もちろん、できるだけ多くのコードを再利用して、ページがアプリケーションの他のページと同じようにスタイル設定されるようにしたいので、ASP.NETページでプレーンなHTMLファイルではなくマスターページを再利用したいと思います。ただし、そうすると、クライアントに提供される実際のHTMLを作成するためのサーバー側の実行可能コードを含むページができます。Stack Overflowの一般的なエラーページの場合、ユーザーが登録されているかどうかを確認し、担当者を取得するなど、その要素をHTMLに挿入するコードです。

そのコードは失敗する可能性があり、その場合、ページが適切に構築されず、サーバーで例外がスローされます。

その状況(エラーページのHTMLを作成するときのエラー)を適切に処理するにはどうすればよいですか?典型的なアプローチは何ですか?

4

2 に答える 2

7

考えられるエラーを分類することから始めたいと思います。

エラーを分類します。

  1. ページが見つかりません (これは完全なログです)。
  2. ハッキングを試みてページのパラメータを壊す
  3. 間違ったユーザー データ入力によるエラー。
  4. 完全に不明なエラー - 修正が必要な新しいバグです。
  5. 非常に難しい一般的なエラー - 何も実行されません - たとえば、データベースがまったく開かれていません。

私たちの目的

エラーページを表示するようになりましたが、まれにのみです。

そのため、ユーザーがページなしでアクションを実行すると、ユーザーの間違った入力をすべてキャプチャし、エラーなしで続行するために何をすべきかをユーザーに示します。

グローバル エラー ハンドラ

global.asaxvoid を使用してすべてのエラーをキャプチャすることから始めることができますApplication_Error(object sender, EventArgs e)

void Application_Error(object sender, EventArgs e) 
{
    try
    {
        Exception LastOneError = Server.GetLastError();

        if (LastOneError != null)
        {
            Debug.Fail("Unhandled error: " + LastOneError.ToString());

            if (!(EventLog.SourceExists(SourceName)))
                EventLog.CreateEventSource(SourceName, LogName);

            EventLog MyLog = new EventLog();
            MyLog.Source = SourceName;
            StringBuilder cReportMe = new StringBuilder();

            cReportMe.Append("[Error come from ip:");
            cReportMe.Append(GetRemoteHostIP());
            cReportMe.Append("] ");
            cReportMe.Append("Last Error:");
            cReportMe.Append(LastOneError.ToString());

            if (LastOneError.ToString().Contains("does not exist."))
            {
                // page not found
                MyLog.WriteEntry(cReportMe.ToString(), EventLogEntryType.Warning, 998);
            }
            else
            {
                MyLog.WriteEntry(cReportMe.ToString(), EventLogEntryType.Error, 999);
            }               
        }
    }
    catch (Exception ex)
    {
        Debug.Fail("Unhandled error: " + GlobalFun.GetErrorMessage(ex));
    }

    string cTheFile = HttpContext.Current.Request.Path;

    // to avoid close loop and stackoverflow
    if(!cTheFile.EndsWith("error.aspx"))
        Server.Transfer("~/error.aspx");
}

このグローバル エラー ハンドルには 1 つの主な目的があります。何が機能していないかを教えて、ここに到達する前に処理に失敗したため、ログに記録し (ログに記録する方法ではありません)、すぐに修正します。コードをデバッグするとき、エラーをすばやく特定できるようにサーバーを転送しませんでした。

ハッキングエラーの場合

この場合、エラーを表示する方が適切ですが、リダイレクトを作成してページをリロードするだけです。ページをハッキングしようとしているかどうかを知る方法は?

ポストバック時にパラメータの CRC/hach エラーが発生した場合は、それを知っています。その回答https://stackoverflow.com/a/2551810/159270を見て、viewstate エラーの例とその処理方法を確認してください。

MVC にはビューステートがなかったことは知っていますが、コードに他の暗号化された文字列、または壊れたときにわかる何らかのセキュリティがある可能性があります。これは一般的な考え方です:

if(IsPostBack && HashErrorOnParametres)
{
  LogIt();
  Responce.Redirect(Request.RawUrl, true);
  return;
}

非常に難しい一般エラーの場合

データベースがまったく開かれていない場合、すべてのユーザーがジェネラル ハンドラーからエラー ページを表示し始めます。プールを再起動したり、過去 5 分間に 20 件のエラーが発生した後にページを停止したり、同様のことを行ったり、電子メールを送信してこの非常に困難なエラーを実行して修正したりする追加のオプションがある場合があります。

残りのソフトエラーについて

考えられるすべての既知のエラーは、try/catch を使用してページ内で処理し、このエラーがユーザーからのものである場合は、何が問題なのかについてのメッセージをユーザーに表示し、もちろんログに記録してそれを確認し、修正する必要があると思います。

ページを部分的に分割すると、1 つの部分でエラーが発生し、残りは正常に機能している可能性があります。これがそれほど重要でない場合は、修正するまで、この部分を単純に非表示にして、残りを表示することができます。たとえば、製品に関する情報を表示するだけで、ある部分について話す部分がエラーをスローする場合、この部分を非表示にしてログで確認し、修正することができます。

を使用して、ページごとにエラーを処理しようとしたことがありますprotected override void OnError(EventArgs e)が、これは役に立たず、削除しました。アクションごとにエラーを処理し、重大でない場合は、修正するまで非表示にします。

残りの通常のエラーがユーザーに表示されます。たとえば、正しいデータが入力されていません...そのためのメッセージと、何を修正するかを伝えます。

私が言うように、私の目標はエラーページをまったく表示しないことです。

于 2012-05-25T09:34:07.043 に答える
1

基本的に、web.config には次のようなものが必要です。

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/Oops.aspx">
</customErrors>

当然、エラー ページへのパスは上記とは異なります。

次のような 404 など、特定のエラーを処理する方法をより一般的にすることができます。

<customErrors mode="RemoteOnly" defaultRedirect="~/ErrorPages/Oops.aspx">
      <error statusCode="404" redirect="~/ErrorPages/404.aspx" />
</customErrors>

編集:

コメントに基づいて、ここに私が得ているものがあります:

「oops.aspx」ページを作成するときは、シンプルに保つことをお勧めします。可能であれば、実行中のコードはまったくありません。「oops.aspx」内のコードを実行する必要がある場合は、そのコードをtry..catchブロックに配置して、例外を使い果たします。

try {
    // Your oops code.
}
catch (Exception e) {
    // Do nothing with the exception.
    // Maybe plonk it in a log file, or System.Diagnostics.Trace.WriteLine(e.Message);
}

ポイントは、「oops.aspx」自体が例外を引き起こしているため、「oops.aspx」が呼び出されるのを避けたいということです。再帰的な問題があります。

マスター ページに try...catch を配置する必要はありません (必要な場合を除きます)。

于 2012-05-25T09:14:58.270 に答える