ASP.NET MVC 区域可以显示自己的一组错误页面吗?

Can an ASP.NET MVC Area display its own set of error pages?

我一直在将我的一些 Web 应用程序整合到一个主要的 ASP.NET MVC 项目中;将其中一些分配给单独的区域,以便可以通过子域访问它们。

使用这个(非常有用的)资源 (https://dusted.codes/demystifying-aspnet-mvc-5-error-pages-and-error-logging),我在 Web.config 中设置了 customErrorshttpErrors,因此自定义错误页面是显示。效果不错。

我将根据 Area/subdomain 使用不同的 layout/styling,所以我想知道: 如何让一个区域显示它自己的一组错误页面?

使用当前设置,所有子域都将显示添加到 customErrorshttpErrors 部分的主要自定义错误集(403.html、404.html等等);但我更喜欢为某些子域量身定制的错误页面。 (例如,如果其中一个区域完全由单独的域完全处理,则提供常规错误页面是不切实际的。)

更新: 根据要求,这是带有代码的场景。感谢 Ben Foster,他在这里提供了很好的指导:http://benfoster.io/blog/aspnet-mvc-custom-error-pages2。我已经放置了 customErrors 的代码,但没有放置相应的 httpErrors...为简洁起见将其省略。

  <system.web>
    <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/500.aspx">
      <error statusCode="404" redirect="~/404.aspx" />
      <error statusCode="500" redirect="~/500.aspx" />
    </customErrors>
  </system.web>

  <location path="MyArea1">
    <system.web>
      <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Areas/MyArea1/500.aspx">
        <error statusCode="404" redirect="~/Areas/MyArea1/404.aspx" />
        <error statusCode="500" redirect="~/Areas/MyArea1/500.aspx" />
      </customErrors>
    </system.web>
  </location>

  <location path="MyArea2">
    <system.web>
      <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="~/Areas/MyArea2/500.aspx">
        <error statusCode="404" redirect="~/Areas/MyArea2/404.aspx" />
        <error statusCode="500" redirect="~/Areas/MyArea2/500.aspx" />
      </customErrors>
    </system.web>
  </location>

以上代码运行良好:

挑战:

现在我想要一个区域 (MyArea2) 由一个完全独立的域(例如 exampleOnMyOtherDomain.com)提供服务,使用 HostDomainConstraint(@TetsuyaYamamoto 在下面的评论中推荐) .本来可以通过 "example.com/MyArea2/validlink" 访问的 link 现在可以这样访问:"exampleOnMyOtherDomain.com/validlink".

现在,如果我尝试 "exampleOnMyOtherDomain.com/does/not/exist",我将获得顶级 404 (~/404.aspx)。这可能是因为 "MyArea2" 已经不在路径中了,所以路径 "MyArea2" 的位置将不会被拾取。

如何让区域 (MyArea2) 为自己的错误页面提供服务?

根据一些研究和@TetsuyaYamamoto 的有用指示,我采用了以下策略。

我正在使用以下代码处理 Global.asax 中的 "Application_Error" 事件:

protected void Application_Error(object sender, EventArgs e)
{
    string hostName = Request.Headers["host"].Split(':')[0];
    if (hostName.Contains("exampleOnMyOtherDomain"))
    {
        Exception exception = Server.GetLastError();
        Response.Clear();
        HttpException httpException = exception as HttpException;
        Response.TrySkipIisCustomErrors = true;

        switch (httpException.GetHttpCode())
        {
            case 404:
                Response.StatusCode = 404;
                Server.Transfer("~/Errors/MyArea2_404.htm");
                break;
            case 500:
            default:
                Response.StatusCode = 500;
                Server.Transfer("~/Errors/MyArea2_500.htm");
                break;
        }
        Server.ClearError();
    }
}

注意事项:

  • hostName.Contains("exampleOnMyOtherDomain") 应该将主机名与我有兴趣处理的区域进行比较。我将为其他领域添加 else...if 语句;
  • Response.TrySkipIisCustomErrors = true 应该阻止 IIS 尝试处理错误;
  • Response.StatusCode 适当设置状态码('404', '500'...);
  • Server.Transfer() 读入一个我想显示为错误页面的文件;
  • Server.ClearError() 应该表示错误已被处理。

我希望 customErrors/httpErrors 继续处理常规错误。当执行通过 Application_Error 块而不被处理时(即 Server.ClearError() 未被调用),customErrors/httpErrors 将处理错误。

对于处理由不同域服务的区域的错误,这似乎是一个不错的策略。