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


116

当有人键入未调用ASP.NET MVC中的有效动作或控制器的URL时,我试图制作一个自定义HTTP 404错误页面,而不是显示一般的“找不到资源” ASP.NET错误。

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

我有什么办法可以捕捉到无效的URL?

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

另一个更新:好的,显然RC1中有一些更改。我什至尝试过专门在上捕获404 HttpException,它仍然只给我“未找到资源”页面。

我什至没有使用过MvcContrib的资源功能,也没有使用-同样的问题。有任何想法吗?



@Peter这是我添加的一个解决方案,它覆盖了HandleUnknownAction以显示不存在操作时的页面未找到视图,然后内置了ASP.net自定义错误处理程序来处理用户可能会键入的其他错误信息。
dswatik


8
当其他用户冒昧时我会讨厌它,并说“为什么要这么做?只要这样做...”,但我建议,如果没有什么阻止您使用web.config方法及其满足您的需求,这是一种标准而优雅的方法。对此方法的任何反馈都值得赞赏,因为很可能会出现我不知道的问题。
肖恩

Answers:


10

只需在路由表的末尾添加catch all route并显示所需的任何页面即可。

请参阅:如何捕获所有路由以处理ASP.NET MVC的“ 404页面未找到”查询?


我想这不过,我仍然得到丑陋的ASP.NET默认未找到资源的短信..
dswatik

3
在此答案或所提供的链接中,我都找不到针对该问题的明确(灵活!)解决方案。
彼得

4
我也不...这似乎是一个不可靠的答案。我正在寻找一种使customErrors行为像在WebForms中一样的方法。有任何想法吗?
JC Grubbs 2010年

1
这两者都不起作用,并且在原则上是不好的。不起作用,因为它不会捕获与早期溃败模式之一匹配的错误URL。原则上不正确,因为它会将应该是错误的错误转换为错误。重定向到名为“错误”的页面与重定向到错误页面不同。您想要将其保留为错误,记录错误,然后将其作为错误进行处理。错误是有价值的信息。
马修(Matthew)

105

我尝试在生产服务器上启用自定义错误3个小时,似乎我找到了最终解决方案,该方法如何在ASP.NET MVC中做到这一点而无需任何路由。

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

  1. 在以下system.web部分的Web配置中配置自定义页面:

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

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

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

      HttpContext.Current.Response.StatusCode = 500;
      HttpContext.Current.Response.TrySkipIisCustomErrors = true;
  3. 在以下system.webServer部分的Web配置中设置另一个魔术设置:

    <httpErrors errorMode="Detailed" />

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


8
这仍然不是理想的解决方案。它没有为您提供正确的HTTP响应代码。customErrors在302重定向中使用结果只是为了加载错误页面。
Justin Helgerson 2014年

@ Ek0nomik我从未见过理想的解决方案:)
Andrew Orsich 2014年

2
@JustinHelgerson我为每个状态代码设置了一个ErrorController,并在这些操作中设置了响应代码,并将响应代码设置得很好。在这两种情况下,我的自定义错误视图都会得到处理
Shane Neuville 2014年

我的队友刚刚删除了共享”文件夹下的“ 错误”视图,以使用此处的此处此处提到的500个状态代码使运行时错误重定向到“自定义错误页面”。希望可以帮助某人。
shaijut

41

通过创建一个ErrorController返回本文中的视图,我可以进行错误处理。我还必须将“全部捕获”添加到global.asax中的路由。

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

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

然后我还添加了:

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

2
谢谢-两年后帮助了我!如果您只想要404的自定义错误,该怎么办?
Shaul Behr

1
一年后@Shaul ...不要设置defaultRedirect,请完全排除该属性。
新泽西州2012年

27

资源

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

您可以使用以下命令通过nuget添加此插件:Install-Package NotFoundMvc

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

分步安装指南:

1-右键单击您的项目,然后选择管理Nuget包...

2-搜索NotFoundMvc并安装。 在此处输入图片说明

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

在此处输入图片说明

4-打开“视图/共享”中新添加的NotFound.cshtml,并根据需要进行修改。现在运行该应用程序,并输入错误的URL,您将看到一个用户友好的404页面。

在此处输入图片说明

不再,用户会收到错误消息,例如 Server Error in '/' Application. The resource cannot be found.

希望这可以帮助 :)

PS:对Andrew Davey制作了如此出色的插件表示敬意。


@niico通过查看源代码,似乎可以将响应代码设置为404,所以可以。
威尔·迪恩

20

在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的更多信息-使用自定义错误页面ASP.NET MVC


1
+1。这对于MVC5的多个区域似乎唯一对我来说是一致的。
霍克2014年

这是最简单的解决方案。不过,您无法在错误页面中使用剃刀语法。
highace

15

此解决方案不需要更改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服务器拦截,因此从不在应用程序级别进行处理。
克里斯·哈克罗

我想补充一下,如果您采用这种方法,建议Response.End();您在Application_Error处理程序的末尾添加a 。如果没有此设置,则只会为给定会话触发首次出现错误,例如,在Application_Error处理程序中具有自定义错误日志记录时,这将成为问题。
基思

6

如果您使用MVC 4,则可以观看解决方案,它对我有用。

将以下Application_Error方法添加到my中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();
    }
}

在GitHub上检查Mvc4CustomErrorPage的完整源代码。


0

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


0

这是真正的答案,可以在一个地方完全自定义错误页面。无需修改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


0

我将讨论一些具体情况,

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

[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

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

//[Route("~/404")]
public ActionResult PageNotFound()
{
  return MyView();
}

而且,如果您将其更改为web.config中的Name方法,那么它将起作用。 但是请不要忘记在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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.