21

私の目標は、MVC 関連だけでなく、管理されているすべてのエラーを処理するエラー処理をアプリケーション内に作成することです。したがって、HandleErrorAttribute パターンは使用していません。これは MVC エラー専用であり、他のマネージド エラー用ではないためです。

私の Global.asax には次のものがあります。

protected void Application_Error()
{
    string displayError = ConfigurationManager.AppSettings["DisplayError"];
    NameValueCollection serverVariables;
    int loop1, loop2;
    StringBuilder serverVariableKeys = new StringBuilder();
    Exception exception = Server.GetLastError();
    HttpException httpException = exception as HttpException;

    if (HttpContext.Current != null)
    {
            // loop through and get server vars
    }

    if (exception != null)
        // Log Error

    // Redirect to Error page if set to basic mode
    if (!string.IsNullOrWhiteSpace(displayError) && displayError.ToLower() == "basic")
    {
        Response.Clear();
    Server.ClearError(); // needed for redirect to work

    var routeData = new RouteData();
    routeData.Values["controller"] = "Error";
    routeData.Values["action"] = "General";
    routeData.Values["exception"] = exception;
    Response.StatusCode = 500;

    if (httpException != null)
    {
       Response.StatusCode = httpException.GetHttpCode();
       switch (Response.StatusCode)
        {
        case 403:
          routeData.Values["action"] = "Http403";
          break;
            case 404:
           routeData.Values["action"] = "Http404";
           break;
        }
    }

    IController errorsController = new Controllers.ErrorController();
    var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
    errorsController.Execute(rc);
    }
}

、およびアクションErrorControllerを持つ があります。各アクションに対応するビューがあります。GeneralHttp403Http404

私のweb.configには次のものがあります:

  <system.web>  
    <!-- removed bits to reduce space -->
    <customErrors mode="On" />
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules >
      <remove name="UrlRoutingModule-4.0" />
      <add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
      <remove name="Session"/>
      <add name="Session" type="System.Web.SessionState.SessionStateModule" preCondition=""/>
    </modules>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <httpErrors errorMode="Detailed" />
  </system.webServer>

これはマネージ コードに関連する多くのシナリオで機能しますが、IIS が無効な静的ファイル呼び出し (example.com/BadFileName.gif) などを引き継ぐと、IIS からエラーが返され、ローカル ファイル パスなどのサーバーの詳細が開示されます。これは、web.config の次の行が原因です。

<httpErrors errorMode="Detailed" />

しかし、errorMode を Custom などの他の値に設定したり、行を削除したりすると、カスタム エラー処理が機能しなくなり、マネージ コード エラーを含むすべてに対して既定の IIS エラー メッセージが返されます。

この設定がなくてもカスタムエラーが機能するように、次のような多くのことを試しました。

  • CustomErrorに設定mode="Off"
  • customErrorコントローラーにリダイレクトするエラーノードを定義する
  • httpErrorsコントローラーにリダイレクトするエラーノードを定義する

デバッグを進めると、コントローラーへの呼び出しが表示されますが、最終的には IIS が代わりに応答を送信します。エラー ログは正しく Application_Error と呼ばれるので、コードはアプリケーションが特定のポイントまでそれを処理できるようにします。

アプリケーションの詳細:

  • ASP.NET MVC 4.0
  • IIS 7.5 でホスト (Azure Web サイト プレビュー)

これを使用して機能させる方法はありません<httpErrors errorMode="Detailed" />か?

4

2 に答える 2

36

この動作が表示される理由は、Application_Errorハンドラーが正しく呼び出されている(そしてコントローラーが呼び出されている)が、IISが500エラーをインターセプトし、独自のエラーページを表示しているためです。Application_Error(ハンドラー自体がをスローしている可能性もありますがException、それは除外したいものです)

すべてのエラー(たとえば、前述の静的ファイルエラー)を処理する必要があるため、最初のエラー検出をASP.NETまたはASP.NETMVCのいずれかに依存できない可能性があります。すべてのエラーがアプリケーションから発生するわけではありません。

最善の方法は、IIS 7.5のエラー処理にできるだけ頼ることであり、早すぎることに関与しようとするのではありません。IISに初期エラー検出を任せれば、はるかに簡単になります。

に次のものを入れてweb.config、既存のhttpErrorsノードを置き換えてみてください。-

<httpErrors errorMode="Custom" existingResponse="Replace">
  <clear />
  <error statusCode="400" responseMode="ExecuteURL" path="/Error" />
  <error statusCode="403" responseMode="ExecuteURL" path="/Error/Forbidden" />
  <error statusCode="404" responseMode="ExecuteURL" path="/Error/NotFound" />
  <error statusCode="500" responseMode="ExecuteURL" path="/Error" />
</httpErrors>

customErrorsノードを完全に削除します。不要です。

エラーコントローラが正しいステータスコードを設定していることを忘れないでください:-

public ActionResult Forbidden()
{
    Response.StatusCode = 403;
    return this.View();
}

そうすれば、ハンドラーからのログアウト以外のすべてを捨てることができるはずです。Application_Errorただし、独自に作成するのが最善だと思いますHttpModulerunAllManagedModulesForAllRequestsのモジュールノードに設定すると、他のweb.config方法ではすり抜けてしまうエラーを見つけるのに役立ちます。

このセットアップ(私は個人的にelmahを使用してログを記録していますが)をAzure Web Sitesプレビューで実行しており、解析の失敗に起因する明らかにエラーを除いて、すべてをキャッチしていますweb.config

カスタムエラーページにhttpErrorsを使用する完全な実例をgithubに掲載しました。AzureWebサイトでもライブで確認できます。

于 2013-01-29T08:41:01.640 に答える
0

アプリでこれを処理したい場合は、カスタム ハンドラーを作成するか、ここで HandleError 属性を使用できます。これは、IIS を松葉杖として使用する代わりに、これにアプローチする 1 つの方法の良い例です。すべての IIS ホスト プロバイダーがサーバー レベルでこの種のカスタマイズを許可しているわけではなく、IMO は展開時に追加の構成が作成されるため、アプローチする方法としては不適切です。

于 2013-01-30T09:28:31.027 に答える