当 运行 在应用程序文件夹中时,无法使自定义错误页面在 ASP.NET MVC 应用程序中工作

Cannot make custom error pages work in ASP.NET MVC application when running in application folder

我有一个 ASP.NET MVC 应用程序,它部署在 IIS 的默认网站中,并在应用程序文件夹中运行,例如http://localhost/appfolder.

我有两个错误页面,我尝试使用 web.config 中的 <httpErrors> 部分设置它们。

<httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="401" />
    <remove statusCode="500" />
    <error statusCode="401" responseMode="ExecuteURL" path="/appfolder/Home/NoAccess" />
    <error statusCode="500" responseMode="ExecuteURL" path="/appfolder/Home/Error" />
</httpErrors>

以上设置有效,但如果不使用路径中的文件夹名称,我无法使其正常工作。基于 documentationpath 属性是相对于站点根目录的。

If you choose the ExecuteURL response mode, the path has to be a server relative URL (for example, /404.htm).

因此,考虑到以上内容,以下内容应该可行,但事实并非如此。

<httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="401" />
    <remove statusCode="500" />
    <error statusCode="401" responseMode="ExecuteURL" path="/Home/NoAccess" />
    <error statusCode="500" responseMode="ExecuteURL" path="/Home/Error" />
</httpErrors>

此外,使用~/Home/NoAccess根本不起作用,似乎IIS只是将~放在URL中。

我的问题:是否可以在不使用应用程序文件夹名称的情况下进行上述设置?

编辑:在此片段中查看我的应用程序如何授权每个请求。

public class AppAutorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        bool authorized = false;
        // Business logic to decide if authorized
        return authorized;
    }

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        base.HandleUnauthorizedRequest(filterContext);
    }
}

它在控制器中的使用是:

[HttpGet]
[AppAutorize]
public ActionResult Item(int id)
{
    Models.Home.Item model = new Models.Home.Item(id);

    return View("Item", model);
}

因为您的 Web 应用程序托管在另一个网站下,错误页面的正确站点相对路径将是您所说的有效路径。我知道这不是您希望看到的,但处理此问题的最佳方法是替换 Web.Release.config 文件中的 httpErrors 元素,如下所示:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document Transform">
    <system.webServer>
        <httpErrors xdt:Transform="Replace">
            <remove statusCode="401" />
            <remove statusCode="500" />
            <error statusCode="401" responseMode="ExecuteURL" path="/appfolder/Home/NoAccess" />
            <error statusCode="500" responseMode="ExecuteURL" path="/appfolder/Home/Error" />
        </httpErrors>
    </system.webServer>
</configuration>

并保持标准 Web.config 路径不包括 appfolder 路径。

我倾向于如何做

我倾向于避免使用网络配置,而是将 HTTP 错误设置为以下内容:

<httpErrors errorMode="DetailedLocalOnly" existingResponse="PassThrough" />

然后我有一个基本控制器,我的所有控制器都继承了它,并为每个我想要自定义页面的错误代码提供了方法。所以在你的情况下:

public ViewResult NoAccess()
{
    Response.StatusCode = (int) HttpStatusCode.Unauthorized;

    return View("NoAccess");
}

那么在你的任何一个控制器中的使用都非常简单:

public ActionResult Test()
{
    return NoAccess();
}

这将呈现您的自定义视图。这种制作错误页面的方法取决于您的用例,但这就是我设法使自定义错误页面起作用的方法。