自定义 ASP.NET MVC 404 错误页面的路由

Posted

技术标签:

【中文标题】自定义 ASP.NET MVC 404 错误页面的路由【英文标题】:Routing for custom ASP.NET MVC 404 Error page 【发布时间】:2010-10-07 22:10:10 【问题描述】:

当有人输入 URL 时,我正在尝试制作自定义 HTTP 404 错误页面 它不会在 ASP.NET MVC 中调用有效的操作或控制器,而是显示通用的“找不到资源”ASP.NET 错误。

我不想使用 web.config 来处理这个问题。

我可以做任何路由魔法来捕获任何无效的 URL 吗?

更新:我尝试了给出的答案,但我仍然收到丑陋的“找不到资源”消息。

另一个更新:好的,显然 RC1 中发生了一些变化。我什至尝试在 HttpException 上专门捕获 404,但它仍然只是给我“找不到资源”页面。

我什至使用了 MvcContrib 的资源功能,但什么也没用——同样的问题。有什么想法吗?

【问题讨论】:

复制***.com/questions/310580/… @Peter 这是我添加的解决方案,同时覆盖 HandleUnknownAction 以在操作不存在时显示页面未找到视图,然后内置 ASP.net 自定义错误处理程序来处理用户可能输入的任何其他内容。 @pete 这也可以***.com/questions/619895/… 我讨厌其他用户冒昧地说“你为什么要这样做?就这样做......”但我建议如果没有什么能阻止你使用 web.config 方法并满足您的需求,这是一种标准且优雅的方法。对此方法的任何反馈表示赞赏,因为它很可能存在一些我不知道的问题。 相关:How can I properly handle 404 in ASP.NET MVC? 【参考方案1】:

我已经尝试在生产服务器上启用自定义错误 3 小时,似乎我找到了最终解决方案如何在没有任何路由的 ASP.NET MVC 中执行此操作。

要在 ASP.NET MVC 应用程序中启用自定义错误,我们需要 (IIS 7+):

    system.web 部分下的 web config 中配置自定义页面:

    <customErrors mode="RemoteOnly"  defaultRedirect="~/error">
        <error statusCode="404" redirect="~/error/Error404" />
        <error statusCode="500" redirect="~/error" />
    </customErrors>
    

    RemoteOnly 表示在本地网络上你会看到真正的错误(在开发过程中非常有用)。我们还可以为任何错误代码重写错误页面。

    设置魔术响应参数和响应状态码(在错误处理模块或错误句柄属性中)

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
    

    system.webServer 部分下的网络配置中设置另一个魔术设置:

    <httpErrors errorMode="Detailed" />
    

这是我发现的最后一件事,之后我可以在生产服务器上看到自定义错误。

【讨论】:

这仍然不是一个理想的解决方案。它不会为您提供正确的 HTTP 响应代码。使用 customErrors 会导致 302 重定向,只是为了加载您的错误页面。 @Ek0nomik 我从未见过理想的解决方案 :) @JustinHelgerson 我为每个状态代码设置了一个 ErrorController 并在这些操作中设置了响应代码,它设置响应代码很好。我用 Fiddler 测试,404 状态代码用 404 响应,页面用500 错误以 500 响应。在这两种情况下,我的自定义错误视图都会提供 我的队友刚刚在Shared 文件夹下删除了错误视图,以使运行时错误500 状态代码重定向到自定义错误页面为提到here 和here。希望对某人有所帮助。【参考方案2】:

我通过创建一个返回本文中的视图的 ErrorController 来进行错误处理。我还必须将“Catch All”添加到 global.asax 中的路线。

如果它不在 Web.config.. 中,我看不到它如何到达这些错误页面中的任何一个?我的 Web.config 必须指定:

customErrors mode="On" defaultRedirect="~/Error/Unknown"

然后我还补充说:

error statusCode="404" redirect="~/Error/NotFound"

【讨论】:

谢谢 - 两年后帮助了我!如果您只想要 404 的自定义错误,您会怎么做? @Shaul 一年后...不要设置 defaultRedirect,完全排除该属性。【参考方案3】:

Source

NotFoundMVC - 只要在 ASP.NET MVC3 应用程序中找不到控制器、操作或路由,就会提供用户友好的 404 页面。 将呈现一个名为 NotFound 的视图,而不是默认的 ASP.NET 错误页面。

您可以使用以下方法通过 nuget 添加此插件: 安装包 NotFoundMvc

NotFoundMvc 在 Web 应用程序启动期间自动安装。它处理 404 HttpException 通常由 ASP.NET MVC 抛出的所有不同方式。这包括缺少的控制器、动作和路由。

分步安装指南:

1 - 右键单击​​您的项目并选择管理 Nuget 包...

2 - 搜索 NotFoundMvc 并安装它。

3 - 安装完成后,两个文件将添加到您的项目中。如下图所示。

4 - 打开 Views/Shared 中新添加的 NotFound.cshtml 并随意修改。现在运行应用程序并输入错误的 url,您将看到一个用户友好的 404 页面。

没有了,用户会收到像Server Error in '/' Application. The resource cannot be found.这样的错误消息

希望这会有所帮助:)

P.S : 感谢 Andrew Davey 制作了这么棒的插件。

【讨论】:

@niico 从查看源代码看来,它似乎将响应代码设置为 404,所以是的。【参考方案4】:

尝试在 web.config 中替换 IIS 错误页面。这是我想的最好的解决方案,它也会发出正确的状态码。

<system.webServer>
  <httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404" subStatusCode="-1" />
    <remove statusCode="500" subStatusCode="-1" />
    <error statusCode="404" path="Error404.html" responseMode="File" />
    <error statusCode="500" path="Error.html" responseMode="File" />
  </httpErrors>
</system.webServer>

更多信息来自Tipila - Use Custom Error Pages ASP.NET MVC

【讨论】:

+1。这是唯一对我来说在多个领域的 MVC5 上始终如一的工作。 这是最简单的解决方案。但是,您不能在错误页面中使用 razor 语法。【参考方案5】:

此解决方案不需要更改 web.config 文件或包罗万象的路由。

首先,像这样创建一个控制器;

public class ErrorController : Controller

    public ActionResult Index()
    
        ViewBag.Title = "Regular Error";
        return View();
    

    public ActionResult NotFound404()
    
        ViewBag.Title = "Error 404 - File not Found";
        return View("Index");
    

然后在“Views/Error/Index.cshtml”下创建视图为;

 @
      Layout = "~/Views/Shared/_Layout.cshtml";
                       
  <p>We're sorry, page you're looking for is, sadly, not here.</p>

然后在 Global asax 文件中添加如下内容:

protected void Application_Error(object sender, EventArgs e)

        // Do whatever you want to do with the error

        //Show the custom error page...
        Server.ClearError(); 
        var routeData = new RouteData();
        routeData.Values["controller"] = "Error";

        if ((Context.Server.GetLastError() is HttpException) && ((Context.Server.GetLastError() as HttpException).GetHttpCode() != 404))
        
            routeData.Values["action"] = "Index";
        
        else
        
            // Handle 404 error and response code
            Response.StatusCode = 404;
            routeData.Values["action"] = "NotFound404";
         
        Response.TrySkipIisCustomErrors = true; // If you are using IIS7, have this line
        IController errorsController = new ErrorController();
        HttpContextWrapper wrapper = new HttpContextWrapper(Context);
        var rc = new System.Web.Routing.RequestContext(wrapper, routeData);
        errorsController.Execute(rc);

        Response.End();

如果您在执行此操作后仍然得到自定义 IIS 错误页面,请确保在 Web 配置文件中将以下部分注释掉(或为空):

<system.web>
   <customErrors mode="Off" />
</system.web>
<system.webServer>   
   <httpErrors>     
   </httpErrors>
</system.webServer>

【讨论】:

我不认为这种方法适用于所有情况,因为 404 经常被 Web 服务器拦截,因此从未在应用程序级别处理。 我想补充一点,如果您采用这种方法,我建议您在 Application_Error 处理程序的末尾添加一个Response.End();。如果没有这个,对于给定的会话,只会触发第一次发生的错误,例如,当您在 Application_Error 处理程序中有自定义错误日志记录时,这是一个问题。【参考方案6】:

只需在路线表的末尾添加捕获所有路线并显示您想要的任何页面。

见:How can i make a catch all route to handle '404 page not found' queries for ASP.NET MVC?

【讨论】:

我试过这个,但我仍然收到丑陋的 ASP.NET 默认资源未找到消息.. 我在这个答案和提供的链接中都没有找到一个明确的(而且灵活的!!)解决方案。 我也没有......这似乎是一个 hacky 的答案。我正在寻找一种让 customErrors 表现得像在 WebForms 中一样的方法。有什么想法吗? 这两者都不起作用并且原则上是不好的。不起作用,因为它不会捕获与早期路由模式之一匹配的错误 URL。原则上不好,因为它将应该错误转换为非错误。重定向到您命名为“错误”的页面与重定向到错误页面不同。您希望将其保留为错误,记录错误,然后将其作为错误处理。错误是有价值的信息。【参考方案7】:

如果您在 MVC 4 中工作,您可以观看 this 解决方案,它对我有用。

将以下 Application_Error 方法添加到我的Global.asax

protected void Application_Error(object sender, EventArgs e)

    Exception exception = Server.GetLastError();
    Server.ClearError();

    RouteData routeData = new RouteData();
    routeData.Values.Add("controller", "Error");
    routeData.Values.Add("action", "Index");
    routeData.Values.Add("exception", exception);

    if (exception.GetType() == typeof(HttpException))
    
        routeData.Values.Add("statusCode", ((HttpException)exception).GetHttpCode());
    
    else
    
        routeData.Values.Add("statusCode", 500);
    

    IController controller = new ErrorController();
    controller.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    Response.End();

控制器本身真的很简单:

public class ErrorController : Controller

    public ActionResult Index(int statusCode, Exception exception)
    
        Response.StatusCode = statusCode;
        return View();
    

查看Mvc4CustomErrorPage at GitHub的完整源代码。

【讨论】:

【参考方案8】:

我遇到了同样的问题,你需要做的是,不要在 Views 文件夹的 web.config 文件中添加 customErrors 属性,而是必须将其添加到项目根文件夹的 web.config 文件中

【讨论】:

【参考方案9】:

这是真正的答案,它允许在单个位置完全自定义错误页面。 无需修改 web.config 或创建单独的代码。

也适用于 MVC 5。

将此代码添加到控制器:

        if (bad) 
            Response.Clear();
            Response.TrySkipIisCustomErrors = true;
            Response.Write(product + I(" Toodet pole"));
            Response.StatusCode = (int)HttpStatusCode.NotFound;
            //Response.ContentType = "text/html; charset=utf-8";
            Response.End();
            return null;
        

基于http://www.eidias.com/blog/2014/7/2/mvc-custom-error-pages

【讨论】:

【参考方案10】:

我会讲一些具体的案例,

如果您在 HomeController 中使用“PageNotFound 方法”,如下所示

[Route("~/404")]
public ActionResult PageNotFound()

  return MyView();

这行不通。但是您必须清除如下所示的 Route 标签,

//[Route("~/404")]
public ActionResult PageNotFound()

  return MyView();

如果您在 web.config 中将其更改为方法名称 它会起作用。 但是不要忘记在 web.config 中执行如下代码

<customErrors mode="On">
  <error statusCode="404" redirect="~/PageNotFound" /> 
 *// it is not "~/404" because it is not accepted url in Route Tag like [Route("404")]*
</customErrors>

【讨论】:

以上是关于自定义 ASP.NET MVC 404 错误页面的路由的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET自定义404和500错误页面

ASP.Net MVC 2 RC2:当所有可选参数为空时,自定义路由返回 404

为啥在asp.net中使用自定义404页面时不存在的页面返回302状态

MVC6 中的自定义选择性 404 页面

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

旧 ASP.Net 应用程序中的自定义错误页面不起作用