错误页面未找到,使用自定义错误页面抛出ELMAH错误

12

我已经对Global.asax进行了一些修改,以便可以显示自定义错误页面(403、404和500)。以下是代码:

    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);
}

但这并没有解决问题。

更新2: 我将一个Error.aspx文件放入共享视图中,只是为了看看会发生什么。当它存在时,ELMAH记录强制异常,然后提供共享视图 - 它从未到达Application_Error()......不太确定如何处理它。

2个回答

27

终于让它满意地运行起来了...

Elmah.Mvc 包应用了一个“隐藏”的错误处理程序。我通过在 web.config 文件的 <appSettings> 中添加以下行来禁用它(默认情况下,该值是从 nuget 安装中设置为“false”)。

<add key="elmah.mvc.disableHandleErrorFilter" value="true" />
所以,现在我的错误会向上传递到Application_Error并被Elmah记录,绕过Elmah过滤器,并显示正确的错误页面(而不是/shared/error.cshtml中的页面)。

4
请确保从FilterConfig中删除默认的MVC错误处理程序。 - solidau
这是elmah.mvc.disableHandleErrorFilter。默认情况下,它是“false”,意味着使用ELMAH.MVC的HandleErrorAttribute()。要禁用它,只需将此设置设置为true即可。 - PussInBoots
为了找到这个解决方案,我费尽了心思! - Grace
这是此事件的最终解决方案,请记得始终应用过滤器的移除。 - Jean Jimenez

1
如果您在IIS 7集成模式下运行,则需要在Application_Error中添加Response.TrySkipIisCustomErrors = true;。否则,尽管您在代码中做了任何事情,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));
}

我之前尝试在“ShowCustomErrorPage”中的“Response.Clear();”前后添加了那个。但都没有起作用 :( - solidau
1
尝试在 Response.ClearError() 之后设置它。那是我设置的位置。 - anwright

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接