首页 文章

asp.net MVC3上的自定义错误页面

提问于
浏览
144

我正在开发一个MVC3基础网站,我正在寻找一个处理错误的解决方案,并为每种错误渲染自定义视图 . 因此,假设我有一个“错误”控制器,其主要操作是“索引”(通用错误页面),并且此控制器将针对用户可能出现的错误(如“Handle500”或“HandleActionNotFound”)执行更多操作 .

因此,网站上可能发生的每个错误都可能由此“错误”控制器处理(例如:“Controller”或“Action”未找到,500,404,dbException等) .

我使用Sitemap文件来定义网站路径(而不是路由) .

This question was already answered, this is a reply to Gweebz

我的最终applicaiton_error方法如下:

protected void Application_Error() {
//while my project is running in debug mode
if (HttpContext.Current.IsDebuggingEnabled && WebConfigurationManager.AppSettings["EnableCustomErrorPage"].Equals("false"))
{
    Log.Logger.Error("unhandled exception: ", Server.GetLastError());
}
else
{
    try
    {
        var exception = Server.GetLastError();

        Log.Logger.Error("unhandled exception: ", exception);

        Response.Clear();
        Server.ClearError();
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "General";
        routeData.Values["exception"] = exception;

        IController errorsController = new ErrorsController();
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        errorsController.Execute(rc);
    }
    catch (Exception e)
    {
        //if Error controller failed for same reason, we will display static HTML error page
        Log.Logger.Fatal("failed to display error page, fallback to HTML error: ", e);
        Response.TransmitFile("~/error.html");
    }
}
}

6 回答

  • 2

    这是我如何处理自定义错误的示例 . 我使用处理不同HTTP错误的操作定义了 ErrorsController

    public class ErrorsController : Controller
    {
        public ActionResult General(Exception exception)
        {
            return Content("General failure", "text/plain");
        }
    
        public ActionResult Http404()
        {
            return Content("Not found", "text/plain");
        }
    
        public ActionResult Http403()
        {
            return Content("Forbidden", "text/plain");
        }
    }
    

    然后我订阅 Global.asax 中的 Application_Error 并调用此控制器:

    protected void Application_Error()
    {
        var exception = Server.GetLastError();
        var httpException = exception as HttpException;
        Response.Clear();
        Server.ClearError();
        var routeData = new RouteData();
        routeData.Values["controller"] = "Errors";
        routeData.Values["action"] = "General";
        routeData.Values["exception"] = exception;
        Response.StatusCode = 500;
        if (httpException != null)
        {
            Response.StatusCode = httpException.GetHttpCode();
            switch (Response.StatusCode)
            {
                case 403:
                    routeData.Values["action"] = "Http403";
                    break;
                case 404:
                    routeData.Values["action"] = "Http404";
                    break;
            }
        }
    
        IController errorsController = new ErrorsController();
        var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
        errorsController.Execute(rc);
    }
    
  • 201

    这里有更多文章如何使用MVC http://kitsula.com/Article/MVC-Custom-Error-Pages创建自定义错误页面 .

  • 3

    您也可以在Web.Config文件中执行此操作 . 这是一个适用于IIS 7.5的示例 .

    <system.webServer>
              <httpErrors errorMode="DetailedLocalOnly" defaultResponseMode="File">
                    <remove statusCode="502" subStatusCode="-1" />
                    <remove statusCode="501" subStatusCode="-1" />
                    <remove statusCode="412" subStatusCode="-1" />
                    <remove statusCode="406" subStatusCode="-1" />
                    <remove statusCode="405" subStatusCode="-1" />
                    <remove statusCode="404" subStatusCode="-1" />
                    <remove statusCode="403" subStatusCode="-1" />
                    <remove statusCode="401" subStatusCode="-1" />
                    <remove statusCode="500" subStatusCode="-1" />
                    <error statusCode="500" path="/notfound.html" responseMode="ExecuteURL" />
                    <error statusCode="401" prefixLanguageFilePath="" path="/500.html" responseMode="ExecuteURL" />
                    <error statusCode="403" prefixLanguageFilePath="" path="/403.html" responseMode="ExecuteURL" />
                    <error statusCode="404" prefixLanguageFilePath="" path="/404.html" responseMode="ExecuteURL" />
                    <error statusCode="405" prefixLanguageFilePath="" path="/405.html" responseMode="ExecuteURL" />
                    <error statusCode="406" prefixLanguageFilePath="" path="/406.html" responseMode="ExecuteURL" />
                    <error statusCode="412" prefixLanguageFilePath="" path="/412.html" responseMode="ExecuteURL" />
                    <error statusCode="501" prefixLanguageFilePath="" path="/501.html" responseMode="ExecuteURL" />
                    <error statusCode="502" prefixLanguageFilePath="" path="/genericerror.html" responseMode="ExecuteURL" />
               </httpErrors>
    </system.webServer>
    
  • 0

    我看到你为 EnableCustomErrorPage 添加了一个配置值,你也在检查 IsDebuggingEnabled 以确定是否运行你的错误处理 .

    由于ASP.NET中已经有一个<customErrors/>配置(完全是出于此目的),因此最简单的说法是:

    protected void Application_Error()
        {
            if (HttpContext.Current == null) 
            {
                    // errors in Application_Start will end up here                
            }
            else if (HttpContext.Current.IsCustomErrorEnabled)
            {
                    // custom exception handling
            }
        }
    

    然后在配置中你可以安装像这样安全的 <customErrors mode="RemoteOnly" /> ,当你需要测试你的自定义错误页面时,你将它设置为 <customErrors mode="On" /> ,这样你就可以验证它是否有效 .

    请注意,您还需要检查 HttpContext.Current 是否为null,因为 Application_Start 中的异常仍将是他的此方法,尽管不会有活动上下文 .

  • 6

    您可以通过实施Jeff Atwood的User Friendly Exception Handling module显示一个用户友好的错误页面,其中包含正确的http状态代码,并略微修改了http状态代码 . 它没有任何重定向工作 . 虽然代码来自2004(!),但它适用于MVC . 它可以完全在您的web.config中配置,根本不会更改MVC项目源代码 .

    this related forum post中描述了返回原始HTTP状态而不是 200 状态所需的修改 .

    基本上,在Handler.vb中,您可以添加如下内容:

    ' In the header...
    Private _exHttpEx As HttpException = Nothing
    
    ' At the top of Public Sub HandleException(ByVal ex As Exception)...
    HttpContext.Current.Response.StatusCode = 500
    If TypeOf ex Is HttpException Then
        _exHttpEx = CType(ex, HttpException)
        HttpContext.Current.Response.StatusCode = _exHttpEx.GetHttpCode()
    End If
    
  • 18

    我正在使用MVC 4.5而且我遇到了Darin解决方案的问题 . 注意:Darin的解决方案很棒,我用它来提出我的解决方案 . 这是我修改过的解决方案:

    protected void Application_Error(object sender, EventArgs e)
    {           
    var exception = Server.GetLastError();
    var httpException = exception as HttpException;
    Response.StatusCode = httpException.GetHttpCode();
    
    Response.Clear();
    Server.ClearError();
    
    
    if (httpException != null)
    {
        var httpContext = HttpContext.Current;
    
        httpContext.RewritePath("/Errors/InternalError", false);
    
        // MVC 3 running on IIS 7+
        if (HttpRuntime.UsingIntegratedPipeline)
        {
            switch (Response.StatusCode)
            {
                case 403:
                    httpContext.Server.TransferRequest("/Errors/Http403", true);
                    break;
                case 404:
                    httpContext.Server.TransferRequest("/Errors/Http404", true);
                    break;
                default:
                    httpContext.Server.TransferRequest("/Errors/InternalError", true);
                    break;
            }
        }
        else
        {
            switch (Response.StatusCode)
            {
                case 403:
                    httpContext.RewritePath(string.Format("/Errors/Http403", true));
                    break;
                case 404:
                    httpContext.RewritePath(string.Format("/Errors/Http404", true));
                    break;
                default:
                    httpContext.RewritePath(string.Format("/Errors/InternalError", true));
                    break;
            }
    
            IHttpHandler httpHandler = new MvcHttpHandler();
            httpHandler.ProcessRequest(httpContext);
        }
    }
    }
    

相关问题