19

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

 <customErrors mode="On" defaultRedirect="Error">
  <error statusCode="404" redirect="Error/NotFound" />
</customErrors>

私は

 [HandleError]

私の HomeController クラスの一番上にあります。テストするために、単純に例外をスローするアクションを作成します。. そしてそれは私の

 ErrorController/Index

メソッドですが、HandleErrorInfoにバインドするビューに到達すると、モデルがnullになるため、エラーへの参照が何らかの形で失われました。

エラーがリダイレクトで失われることに関係があると確信しているので、何かが欠けているかどうか、スタックトレースとエラーメッセージを表示するビューを表示できる提案があるかどうかを確認したかったのです。

4

3 に答える 3

6

すべてのエラー (HandleError 属性を持つコントローラーで発生するエラーだけでなく) を処理する maxlego と同様のことを行います。

私の MvcApplication クラス (global.asax.cs 内) には次のものがあります。

public class MvcApplication : HttpApplication
{
    // usual stuff here...

    protected void Application_Error(object sender, EventArgs e)
    {
        Server.HandleError(((MvcApplication)sender).Context);
    }
}

上記のコードは、便利なものの MVC ライブラリの拡張メソッドを使用しています。これにより、エラー処理属性、customErrors 構成、またはカスタム フィルターは必要ありません。代わりに、拡張メソッドはエラーの詳細をログに記録し、次のいずれかの適切なビューを呼び出します。

  • アクセスが拒否されました
  • 見つかりません
  • 内部サーバーエラー

これを機能させるための拡張メソッド コードは次のとおりです。

public static class HttpServerUtilityExtensions
{
    private static readonly Logger Logger = LogManager.GetCurrentClassLogger();

    public static void HandleError(this HttpServerUtility server, HttpContext httpContext)
    {
        var currentController = " ";
        var currentAction = " ";
        var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));

        if (currentRouteData != null)
        {
            if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
                currentController = currentRouteData.Values["controller"].ToString();

            if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
                currentAction = currentRouteData.Values["action"].ToString();
        }

        var exception = server.GetLastError();
        Logger.ErrorException(exception.Message, exception);

        var controller = DependencyResolver.Current.GetService<ErrorController>();
        var routeData = new RouteData();
        var action = "InternalServerError";

        if (exception is HttpException)
        {
            var httpEx = exception as HttpException;

            switch (httpEx.GetHttpCode())
            {
                case 404:
                    action = "NotFound";
                    break;

                case 401:
                    action = "AccessDenied";
                    break;
            }
        }

        httpContext.ClearError();
        httpContext.Response.Clear();
        httpContext.Response.StatusCode = exception is HttpException ? ((HttpException)exception).GetHttpCode() : 500;
        httpContext.Response.TrySkipIisCustomErrors = true;

        routeData.Values["controller"] = "Error";
        routeData.Values["action"] = action;

        controller.ViewData.Model = new HandleErrorInfo(exception, currentController, currentAction);
        ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
    }
}

上記では、エラーの詳細を記録するために NLog を使用していますが、他の何かをサポートするように簡単に変更できます。また、このメソッドは、ErrorController を解決するときに IoC コンテナーを尊重します。

于 2013-05-08T19:02:29.620 に答える