【问题标题】:Can an ASP.NET MVC Area display its own set of error pages?ASP.NET MVC 区域可以显示它自己的一组错误页面吗?
【发布时间】:2017-02-19 10:08:53
【问题描述】:

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

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

我将为每个区域/子域使用不同的布局/样式,所以我想知道: 我怎样才能让一个区域显示它自己的一组错误页面?

在当前设置下,所有子域都将显示添加到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>

上面的代码运行良好:

  • 如果我导航到“example.com/does/not/exist”,我会得到 ~/404.aspx 的预期错误页面。
  • 如果我导航到“example.com/MyArea1/does/not/exist”,我会 在~/Areas/MyArea1/404.aspx 获取自定义错误页面。

挑战:

现在,我希望使用 HostDomainConstraint(@TetsuyaYamamoto 推荐,在下面的评论中)由一个完全独立的域(例如 exampleOnMyOtherDomain.com)提供一个区域(MyArea2)。可以通过“example.com/MyArea2/validlink”访问的链接现在可以通过以下方式访问:“exampleOnMyOtherDomain.com/validlink”。

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

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

【问题讨论】:

  • 位置设置可能会有所帮助,请参阅参考:msdn.microsoft.com/en-us/library/ms178692.aspx。它可以在每个位置的&lt;system.web&gt;元素内包含不同的内容,允许通过指定区域相对路径为不同区域设置customErrorshttpErrors
  • 感谢@TetsuyaYamamoto;这是一个非常有用的评论。我尝试了location 元素,当我的区域是我的主域的子路径(例如example.com/MyArea)时,location 元素工作得很好(path="MyArea")!但问题是:当我的区域完全由一个单独的域提供服务时,我不能使用相同的策略(例如myotherexample.net)。
  • 访问 myotherexample.net 时显示什么样的错误?可能它应该需要在 Global.asax 路由模块中使用HostNameContraint 进行额外的路由配置(还包括对该区域的 URL 重写)。此外,您可以编辑您的问题以包括区域和路线代码。
  • 感谢@TetsuyaYamamoto;编辑了问题。
  • 查看您的 web.config 区域设置后,我假设您可以使用 Application_Error 处理从 myotherexample.net 到 MyArea2 的错误,使用 Request.Url.Host。此外,您可以将MapRoute 设置为处理MyArea2 作为重定向区域路径的一部分,然后设置IIS URL 重写模块:iis.net/expand/URLRewrite

标签: asp.net-mvc web-config custom-errors


【解决方案1】:

根据@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 将处理错误。

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

【讨论】:

  • 恕我直言,此策略能够实现自定义错误页面的分离域处理,但是您需要注意 TrySkipIisCustomErrors 是否正常工作。如果重定向到区域错误页面不起作用,如果 IIS 已设置为集成模式,请检查 &lt;httpErrors errorMode="Custom" existingResponse="PassThrough" /&gt; 是否到位,请参阅此参考:msdn.microsoft.com/en-us/library/ms690576(v=vs.90).aspx
  • 会的。感谢@TetsuyaYamamoto,感谢您的帮助!
  • 我有类似的问题,我尝试为每个区域设置不同的自定义404页面?我的 web.config 中有这个 httpErrors 这路由主 404 页面,但如果路由有area myhost/area/notfound/route 应该显示 myhost/myArea/Error/NotFound。我应该问一个新问题,如果不是,我应该如何修改这个解决方案?
猜你喜欢
  • 2012-06-29
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-10-07
  • 2018-11-23
  • 1970-01-01
  • 1970-01-01
  • 2011-04-09
相关资源
最近更新 更多