12

カスタム エラー ページ (403、404、および 500) を表示できるように、Global.asax にいくつかの変更を加えました。コードは次のとおりです。

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            //FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }

        protected void Application_Error(object sender, EventArgs e)
        {
            if (Context.IsCustomErrorEnabled)
            {
                ShowCustomErrorPage(Server.GetLastError());
            }
        }

        private void ShowCustomErrorPage(Exception exception)
        {
            HttpException httpException = exception as HttpException;
            if (httpException == null)
            {
                httpException = new HttpException(500, "Internal Server Error", exception);
            }

            Response.Clear();
            RouteData routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("fromAppErrorEvent", true);

            switch (httpException.GetHttpCode())
            {
                case 403:
                    routeData.Values.Add("action", "AccessDenied");
                    break;

                case 404:
                    routeData.Values.Add("action", "NotFound");
                    break;

                case 500:
                    routeData.Values.Add("action", "ServerError");
                    break;

                default:
                    routeData.Values.Add("action", "DefaultError");
                    routeData.Values.Add("httpStatusCode", httpException.GetHttpCode());
                    break;
            }

            Server.ClearError();

            IController controller = new ErrorController();
            controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
        }
    }

また、Web.Config に以下を追加しました。

<customErrors mode="On">
    <!-- There is custom handling of errors in Global.asax -->
</customErrors>

カスタム エラー ページは正しく表示され、ELMAH は (意図的に) スローされたエラーを正しくログに記録します。ただし、ELMAH は追加のエラーもキャッチしてログに記録します。

System.InvalidOperationException: The view 'Error' or its master was not found or no view engine supports the searched locations. The following locations were searched: ~/Views/account/Error.aspx ~/Views/account/Error.ascx ~/Views/Shared/Error.aspx ~/Views/Shared/Error.ascx ~/Views/account/Error.cshtml ~/Views/account/Error.vbhtml ~/Views/Shared/Error.cshtml ~/Views/Shared/Error.vbhtml

私の最初の本能はHandleErrorAttribute、フィルター構成でグローバルを無効にすることにつながりました。そして、次のような同様の SO の質問:カスタム エラー ページでの MVC の問題により、私の疑いが正しいと信じるようになりました。しかし、グローバルHandleErrorAttributeを無効にした後でも、エラービューが見つからないというエラーが表示されます! 何を与える?System.Web.Mvc.Controller 私の唯一の他の予感は、ソースを調べて、HandleErrorAttributeが適用されているかどうかを確認しようとしSystem.Web.Mvc.Controllerたが、何も収集できなかったことに由来するということです...

更新:ベースコントローラーをオーバーライドして、例外を次のように処理されるようにマークしようとしました:

protected override void OnException(ExceptionContext filterContext)
{
    filterContext.ExceptionHandled = true;
    base.OnException(filterContext);
}

しかし、それは問題を解決しませんでした。

UPDATE2:何が起こるかを確認するために、共有ビューに Error.aspx ファイルを配置しました。そこにある場合、ELMAHは強制例外をログに記録し、共有ビューが提供されます-到達することはApplication_Error() ありません....どうすればよいかわかりません。

4

2 に答える 2

27

最終的には満足のいく動作になりました...

Elmah.Mvc パッケージは、「隠し」エラー ハンドラを適用します。web.config に次の行を追加して、これを無効にしました<appSettings>(値は、nuget インストールからデフォルトで「false」に設定されていました)。

<add key="elmah.mvc.disableHandleErrorFilter" value="true" />

そのため、エラーは Application_Error まで伝播し、Elmah フィルターをバイパスして Elmah によってログに記録され、適切なエラー ページが表示されます (/shared/error.cshtml のエラー ページではありません)。

于 2013-05-22T23:22:48.013 に答える
1

IIS 7 統合モードで実行している場合はResponse.TrySkipIisCustomErrors = true;、Application_Error を追加する必要があります。そうしないと、コードで何を行っても、IIS はクライアントをカスタム エラー ページにリダイレクトします。

詳細については、http ://www.west-wind.com/weblog/posts/2009/Apr/29/IIS-7-Error-Pages-taking-over-500-Errors を参照してください。

編集: これが私の Application_Error の本体です:

if (HttpContext.Current != null)
{
    Server.ClearError();
    Response.TrySkipIisCustomErrors = true;
    RouteData data = new RouteData();
    data.Values.Add("controller", "Error");
    data.Values.Add("action", "Error");
    IController controller = new MyApp.Controllers.ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), data));
}
于 2013-05-22T21:04:16.370 に答える