2

这是我定义它的方式(在本地,在我的开发机器上):

    <customErrors mode="On" defaultRedirect="Error.aspx">
        <error statusCode="404" redirect="NotFound.aspx" />
    </customErrors>

我有 [HandleError] 属性:

[Authorize]
[HandleError]
public class HomeController : Controller
{ // etc.

然而,当我输入http://localhost:1986/blah时,我收到以下错误:

无法找到该资源。说明:HTTP 404。您要查找的资源(或其依赖项之一)可能已被删除、名称已更改或暂时不可用。请查看以下 URL 并确保其拼写正确。

请求的 URL:/NotFound.aspx

它尝试访问的 URL 与您期望的一样: http://localhost:1986/NotFound.aspx?aspxerrorpath=/blah

所以它正试图去自定义错误文件——但是它找不到它。我在 Shared 目录中有 NotFound.aspx——与 Microsoft 默认提供的 Error.aspx 相同。为什么找不到呢?

4

3 回答 3

3

如果 Error.aspx 和 NotFound.aspx 位于共享目录中,是否有连接到为它们提供服务的控制器?如果您没有配置某种控制器路由来提供文件,那么它们在共享文件夹中的事实是无关紧要的。

您有几个选项,您可以创建一个 ErrorController 来处理对这些视图的请求并定义指向这些控制器操作的路由:

[OutputCache(CacheProfile = "Default", VaryByParam = "none")]
public class ErrorController : DefaultAreaBaseController
{
    public ViewResult ServiceUnavailable() {
        Response.StatusCode = (int)HttpStatusCode.ServiceUnavailable;

        return View("ServiceUnavailable");
    }

    public ViewResult ServerError() {
        Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        return View("ServerError");
    }

    public new ViewResult NotFound() {
        Response.StatusCode = (int)HttpStatusCode.NotFound;

        return View("NotFound");
    }
}

或者作为替代方案,您可以创建指向物理文件的忽略路由,并将错误页面放置在 Views 文件夹以外的位置(如根目录):

routes.IgnoreRoute("Error.aspx/{*pathInfo}");
routes.IgnoreRoute("NotFound.aspx/{*pathInfo}");

这些解决方案中的任何一个都是可行的,但是根据您的配置,使用 IgnoreRoute() 可能更理想,因为它不需要将请求通过管道传输到 MVC 以提供静态错误页面。

于 2010-08-05T16:56:25.803 回答
3

选项一:

是构建一个带有“NotFound”视图和“Unknown”视图的错误控制器。这将接受任何 500 服务器错误或 404 NotFound 错误并将您重定向到适当的 URL。我并不完全喜欢这个解决方案,因为访问者总是被重定向到错误页面。

http://example.com/Error/Unknown

<customErrors mode="On" defaultRedirect="Error/Unknown">
    <error statusCode="404" redirect="Error/NotFound" />
    <error statusCode="500" redirect="Error/Unknown" />
</customErrors>
  • wwwroot/
    • 控制器
      • 错误.cs
    • 观看次数/
      • 错误/
      • 未找到.aspx
      • 未知.aspx

选项二:

绝对不喜欢这种方法(因为它基本上是恢复到 Web 表单,第二种选择是简单地拥有一个静态 Error.aspx 页面并忽略 MVC 中的路由),但它仍然有效。您在这里所做的是忽略“静态”目录,将您的物理错误页面放在那里,并绕过 MVC。

routes.IgnoreRoute("/Static/{*pathInfo}");  //This will ignore everything in the "Static" directory
  • wwwroot/
    • 控制器/
    • 静止的/
      • 错误.aspx
    • 观看次数/

选项三:

第三个选项(这是我最喜欢的)是从捕获错误的任何视图返回一个错误视图。这将要求您在“已知”错误的过程中编写 Try/Catch 块,然后您可以使用 HandleError 处理可能出现的未知错误。这将保留最初请求的 URL,但返回 ERROR 视图。

示例:
http ://example.com/Products/1234将显示 ProductID 1234 的详细信息页面
http://example.com/Products/9999将显示NotFound错误页面,因为 ProductID 9999 不存在
http://example .com/Errors/NotFound “应该”永远不会显示,因为您在控制器中单独处理这些错误。

网络配置

<customErrors mode="On">
</customErrors>

控制器

// Use as many or as few of these as you need
[HandleError(ExceptionType = typeof(SqlException), View = "SqlError")]
[HandleError(ExceptionType = typeof(NullReferenceException), View = "NullError")]
[HandleError(ExceptionType = typeof(SecurityException), View = "SecurityError")]
[HandleError(ExceptionType = typeof(ResourceNotFoundException), View = "NotFound")]
Public Class ProductController: Controller{
    public ViewResult Item(string itemID)
    {
        try
        {
            Item item = ItemRepository.GetItem(itemID);
            return View(item);
        }
        catch()
        {
            return View("NotFound");
        }
    }
}

文件夹结构

  • wwwroot/
    • 控制器/
    • 共享/
      • 未找到.aspx
      • 空错误.aspx
      • 安全错误.aspx
      • SqlError.aspx
    • 观看次数/

选项四:

最后一个选项是您为之类的东西构建自己的自定义过滤器ResourceNotFoundException并将其附加到您的控制器类。这将做与上面完全相同的事情,但还有一个额外的好处,就是将错误代码也发送到客户端。

Richard Dingwall 在他的博客上谈到了它

于 2010-08-05T17:05:29.397 回答
0

您在这里混合 Web 表单和 MVC 概念。在 web.config 中关闭自定义错误。然后在 HandleError 属性中可选地指定类型和视图,默认情况下在 views\CurrentController 然后在 views\shared 中搜索 error.aspx。虽然您可以使用 HandleError 过滤器进行 404 处理,但您可能希望创建一个仅用于 404 处理的过滤器,原因和如何在此处详细说明:

http://richarddingwall.name/2008/08/17/strategies-for-resource-based-404-errors-in-aspnet-mvc/

于 2010-08-05T18:07:12.697 回答