5

リリース間近のMVC2Webアプリケーションがあります。これまでカスタムエラーをオフにしていましたが、本番環境に移行するときにそれらを機能させたいと思います。

次のようにweb.configを設定しました。

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

404は完全に機能し、NotFoundは、自分のSite.Masterファイルを使用してかなり標準的な404ページを表示するビューに直接マップするアクションです。

404以外の場合は、ユーザーが例外の詳細を表示できるようにする必要があります。(これは内部アプリケーションであり、そうすることでセキュリティリスクはありません)。

ErrorデフォルトのアクションIndexは、私が定義したView()を返すように設定されています。私が理解できないのは、例外情報をビューに渡す方法です。

これは有望に見えました:

http://devstuffs.wordpress.com/2010/12/12/how-to-use-customerrors-in-asp-net-mvc-2/

しかし、ビューを次のように使用すると、次のようになります。

<%@ Page Title="" Language="C#" 
    MasterPageFile="~/Views/Shared/Bootstrap.Master"
    Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>

HandleErrorInfoがnullであるため、エラーページ自体がエラーをスローします。明らかに、カスタムエラーのエラーは、MVC2に多くの問題を引き起こし、その結果、死の黄色い画面が表示されます。

ブログで何かキーを見逃したか、コントローラー/アクションのすべてにError属性を設定せずにHandleErrorInfoをnull以外にする方法が説明されていないのではないかと思います。

また、MVC3がこれをより適切に処理することを認識しており、Razorが非常に優れていることを認識しています。このプロジェクトでは使用されていません。また、このプロジェクトを使用するように変更されることもありません。したがって、「MVC3を使用する」という回答はしないでください。

4

1 に答える 1

12

HandleErrorInfoでリダイレクトを実行しているため、はnullですcustomErrors

これは私が最新のプロジェクトで試しているアイデアであり、MVC 2用に更新しましcustomErrorsた。リダイレクトを実行せずにコントローラーアクションを呼び出すことができないため、使用しませんでした(おそらく)。

アプリケーションエラー

protected void Application_Error(Object sender, EventArgs e)
{
    GlobalErrorHandler.HandleError(((HttpApplication)sender).Context, Server.GetLastError(), new ErrorController());
}

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

public class GlobalErrorHandler
{
    public static void HandleError(HttpContext context, Exception ex, Controller controller)
    {
        LogException(ex);

        context.Response.StatusCode = GetStatusCode(ex);
        context.ClearError();
        context.Response.Clear();
        context.Response.TrySkipIisCustomErrors = true;

        if (IsAjaxRequest(context.Request))
        {
            ReturnErrorJson(context, ex);
            return;
        }

        ReturnErrorView(context, ex, controller);
    }

    public static void LogException(Exception ex)
    {
        // log the exception
    }

    private static void ReturnErrorView(HttpContext context, Exception ex, Controller controller)
    {
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";
        routeData.Values["action"] = GetActionName(GetStatusCode(ex));

        controller.ViewData.Model = new HandleErrorInfo(ex, " ", " ");
        ((IController)controller).Execute(new RequestContext(new HttpContextWrapper(context), routeData));
    }

    private static void ReturnErrorJson(HttpContext context, Exception ex)
    {
        var json = string.Format(@"success: false, error:""{0}""", ex.Message);
        context.Response.ContentType = "application/json";
        context.Response.Write("{" + json + "}");
    }

    private static int GetStatusCode(Exception ex)
    {
        return ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
    }

    private static bool IsAjaxRequest(HttpRequest request)
    {
        return request.Headers["X-Requested-With"] != null && request.Headers["X-Requested-With"] == "XMLHttpRequest";
    }

    private static string GetActionName(int statusCode)
    {
        string actionName;

        switch (statusCode)
        {
            case 404:
                actionName = "NotFound";
                break;

            case 400:
                actionName = "InvalidRequest";
                break;

            case 401:
                actionName = "AccessDenied";
                break;

            default:
                actionName = "ServerError";
                break;
        }

        return actionName;
    }

    public static bool IsDebug
    {
        get
        {
            bool debug = false;

#if DEBUG
            debug = true;
#endif
            return debug;
        }
    }
}

エラーコントローラー

public class ErrorController : Controller
{
    public ActionResult AccessDenied()
    {
        return View("AccessDenied");
    }

    public ActionResult InvalidRequest()
    {
        return View("InvalidRequest");
    }

    public ActionResult NotFound()
    {
        return View("NotFound");
    }

    public ActionResult ServerError()
    {
        return View("ServerError");
    }
}

ServerErrorビュー

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    ServerError
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>ServerError</h2>

    <% if (Model.Exception != null ) { %>
        <p>
          Controller: <%= Model.ControllerName %>
        </p>
        <p>
          Action: <%= Model.ActionName %>
        </p>
        <p>
          Message: <%= Model.Exception.Message%>
        </p>
        <p>
          Stack Trace: <%= Model.Exception.StackTrace%>
        </p>
    <% } %>

</asp:Content>
于 2012-07-18T14:12:56.110 に答える