【问题标题】:Custom Error in MVC 4MVC 4 中的自定义错误
【发布时间】:2013-11-08 22:27:30
【问题描述】:

我在处理 MVC 中的错误时遇到问题。我的目标是在标题中显示“友好”错误消息,但应用程序应该已经可见。 我在基本控制器方法上使用覆盖 OnException 如下:

protected override void OnException(ExceptionContext filterContext)
{
    if (filterContext.ExceptionHandled)
        return;

    var error = new ErrorModel(filterContext.Exception);
    error.ActionName = filterContext.RouteData.Values["action"].ToString();
    error.ControllerName = filterContext.RouteData.Values["controller"].ToString();

    filterContext.Controller.TempData["ErrorInfo"] = error;

    filterContext.HttpContext.Response.Clear();
    filterContext.HttpContext.Response.StatusCode = 500;
    filterContext.ExceptionHandled = true;
    filterContext.Result = this.RedirectToAction(actionName: "DisplayError", controllerName: "Error");            

    //base.OnException(filterContext);
}

ErrorModel 是 HandleErrorInfo 的平面副本,因为所有操作都需要序列化。

在 ErrorController 中,我从 TempData 检索我的模型

public ActionResult DisplayError()
{
    var error = TempData["ErrorInfo"] as ErrorModel;
    ControllerContext.HttpContext.Response.StatusCode = 500;

    return PartialView("Error", error);
}

我称之为我的观点

@using log4net;
@model Easily.MVC.Utils.ErrorModel
@{
    ViewBag.Title = "Error";
}

    <link href="@string.Format("http://{0}/easily.Ressources.Web/css/easilyCommon.min.css", System.Configuration.ConfigurationManager.AppSettings["EasilyServerName"])" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/custom.css")?v=@Html.Action("GetVersion", "Main")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/Worklist.css")?v=@Html.Action("GetVersion", "Main")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/jquery.contextMenu.css")?v=@Html.Action("GetVersion", "Main")" rel="stylesheet" type="text/css" />
    <script type="text/javascript"> window['currentPath'] = '@Url.Content("~/")'; </script>
    <script src="@string.Format("http://{0}/easily.Ressources.Web/js/easilyCommon.min.js", System.Configuration.ConfigurationManager.AppSettings["EasilyServerName"])" type="text/javascript"></script>

<fieldset class="divError">
    @if (ViewBag != null && ViewBag.Message != null)
    {
        <legend title="Erreur Easily.MVC" class="legendError">Une erreur s'est produite</legend>@*
         <span>Erreur Easily.MVC</span>*@
    }
    @if (Model != null /*&& HttpContext.Current.IsDebuggingEnabled*/)
    {
        <legend title="Erreur @Model.Exception.Message" class="legendError">Une erreur s'est produite</legend>@*
        <span>Erreur @Model.Exception.Message</span>*@
    }

    <div class="detailError">
        <h3>Detail de l'erreur</h3>
        <div class="list-sfs-holder msgError">
            @if (ViewBag != null && ViewBag.Message != null)
            {
                <div class="alert alert-error">@ViewBag.Message</div>
            }
            @if (Model != null /*&& HttpContext.Current.IsDebuggingEnabled*/)
            {
                <div>
                    <p>
                        <b>Exception:</b> @Model.Exception.Message<br />
                        <b>Controller:</b> @Model.ControllerName<br />
                        <b>Action:</b> @Model.ActionName
                    </p>
                    <hr />
                    <p>
                        <b>StackTrace:</b>
                    </p>
                    <div style="overflow: scroll; width: 980px;">

                            <pre>
                         @Model.Exception.StackTrace
                </pre>

                    </div>
                </div>
            }

        </div>
    </div>
</fieldset>

@{
    ILog log = LogManager.GetLogger("WorkListError");

    if (ViewBag != null && ViewBag.Message != null)
    {
        log.Error("ViewBag.Message:" + @ViewBag.Message);
    }
    if (Model != null && HttpContext.Current.IsDebuggingEnabled)
    {
        log.Error("Exception:" + Model.Exception.Message + "|" +
                   "Controller:" + Model.ControllerName + "|" +
                   "Action:" + Model.ActionName + "|" +
                   "StackTrace:" + Model.Exception.StackTrace
                 );
    }    
}

<script>

    $(document).ready(function () {
        $(".detailError").accordion({ collapsible: true, active: false, heightStyle: "content", width: '980px' });
    });

</script>

至少,对于 AJAX 错误,我使用这个脚本:

$(document).ajaxError(function (event, jqxhr, settings, exception) {
    $("#error_content").html(jqxhr.responseText);
});

有了这段代码,结果就是我的目标@localhost。但是当我在测试服务器上部署它时,我有服务器消息错误 500 而不是我的错误视图。那么如何修改代码以避免错误 500 并在自定义显示中捕获错误(服务器无法修改,但我可以使用 web.config)?如果我评论 ControllerContext.HttpContext.Response.StatusCode = 500;在 DisplayError 中,没有捕获到 Ajax 错误。

感谢您的帮助。

【问题讨论】:

  • 我不知道这是否回答了您的问题(可能没有),但您可以(并且在我看来应该)返回一个状态码 500 以及您的错误视图,而不是重定向到错误页面。这让事情变得更清晰、更容易调试并且易于实现。
  • 另外,您应该在控制器内部使用日志库,而不是在视图内部。
  • 是的,你是对的。 ErrorController 和 BaseController 位于单独的公共 dll 中。视图在使用 dll 的项目中。下一步是在此 dll 中集成 View 并从此 dll 进行日志记录。但这将在另一个 StackOverflow 问题中;)

标签: c# asp.net-mvc asp.net-mvc-4 error-handling


【解决方案1】:

在您的web.config 中,确保您具有以下配置:

<configuration>
    <system.webServer>
        <httpErrors errorMode="Detailed" />
    </system.webServer>
</configuration>

errorMode 的默认值为DetailedLocalOnly (docs)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多