Url.Action在某些环境中返回空字符串

问题描述 投票:8回答:2

我有一个Sitecore站点,在我的两个CD服务器上,Url.Action返回一个空字符串。这适用于本地和其他9个服务器,从开发到产品,CD和CM。

部署自动化确保将完全相同的web.config部署到所有环境中;同样适用于所有其他配置。

我的控制器正确地继承了SitecoreController。这不会与某个控制器或操作隔离,所有控制器和操作都会发生这种情况。

什么会使Url.Action在一个环境中返回一个空字符串而不是其他环境,使用相同的代码?

asp.net-mvc asp.net-mvc-routing sitecore8 sitecore-mvc
2个回答
6
投票

什么会使Url.Action有时会返回一个空字符串?

具体而言,路由从当前请求派生的值。

说明

Url.Action方法由UrlHelper驱动,而Url.Action又由路线驱动。它使用路由值来确定用于构建URL的路由。路由框架尝试按照它们注册的顺序将每个路由与路由值进行匹配,直到找到匹配为止。如果路由框架到达路由表的末尾并且仍然没有匹配,则返回一个空字符串(因为没有其他合理的默认行为)。

另一方面,如果您调用Url.Action并传递路径名称,则会将可能的匹配范围缩小到仅1个特定路径(命名路径)。但是路由值仍然需要匹配该路由,否则您将获得默认的空字符串。

通常,所有路由值必须匹配,但有一些事情可能使行为古怪:

  1. 路线值可以是可选的。这意味着路由值不需要存在以使路由匹配。
  2. 如果在调用Url.Action时未提供路由值,则可以在当前请求中存在时自动提供该路由值。

第二个怪癖意味着如果将public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "AboutWith4RouteValues", url: "test/home/about/{foo}/{bar}", defaults: new { controller = "Home", action = "About" }); routes.MapRoute( name: "ContactWith4RouteValues", url: "test/home/contact/{foo}/{bar}", defaults: new { controller = "Home", action = "Contact", bar = UrlParameter.Optional }); routes.MapRoute( name: "Home", url: "", defaults: new { controller = "Home", action = "Index" } ); } } 放在共享视图上,并且一个请求包含路由值以使其与路由匹配,而另一个请求不包含该路由值,则在后一种情况下,URL可能与另一个路由匹配可能是一个空字符串。

假设路由配置设置如下:

_Layout.cshtml

另外,假设<a href='@Url.Action("About", "Home")'>About</a> 页面上有一个链接:

/

如果您转到浏览器的主页(<a>About</a> ),结果链接URL将是:

foo

这是因为barUrl.Action不存在于请求的路由值中,因此它与任何已注册的路由都不匹配。

实际上,href=''返回一个空字符串,但Razor优化了空的/test/home/contact/arg1/arg2 属性。

另一方面,如果您将此URL放在浏览器中:

<a href='/test/home/about/arg1/arg2'>About</a>

链接URL生成为:

{foo}

这是因为当前请求中都有arg1(值{bar})和arg2(值ContactWith4RouteValues)。请注意,传入请求与AboutWith4RouteValues路由匹配,但是当生成链接URL时,它使用foo路由。由于bar/test/home/contact/arg1 都存在于请求中,因此它们会被转移到URL的生成中。

现在,如果浏览器中的URL更改为:

ContactWith4RouteValues

它仍然匹配<a>About</a> 路线,因为最后一个值是可选的。但是,生成的URL现在是:

foo

这是因为bar在请求中有一个值,但是Url.Action没有值,AboutWith4RouteValues生成请求与bar不匹配,因为Home是一个必需的值,以使其匹配。由于它也与Url.Action路由不匹配,我们已到达路由表的末尾,唯一合理的返回是空字符串。

解决方法

避免当前请求的这些怪癖的最简单的解决方法是在调用UrlHelper或其他基于ActionLink的方法(例如RedirectToRoute<a href='@Url.Action("About", "Home", new { foo = Model.Foo, bar = Model.Bar })'>About</a> 等)时手动指定路由值。

Url.Action

这可确保在构建URL时始终存在这些值,即使它们不是当前请求的一部分。


0
投票

我有这个完全相同的问题,对我来说,问题与我的路由中的Case-Sensitivity有关。 将同一站点部署到同一IIS Web服务器上的两个不同应用程序。 我使用了相同的web-config和相同的VS Web发布设置。 然而,我的WorkBench在Prod中返回空白(空字符串),但在Dev中没有。 在查看代码后,有些东西引起了我的注意。

我有一个名为B的区域(大写“Url.Action”)。 在一些地方(Workbench返回空白),我正在传递b(小写“RouteConfig.cs”)。 我的WorkBenchAreaRegistration.cs和区域注册(即b)有一些奇特的逻辑。 在这些文件中,我使用条件逻辑来确定应用程序运行的环境。 我使用相同的项目来共享代码,但只希望在不同的环境中可以访问某些区域。 即使Prod和Dev是不同的环境,要调试这个问题, 我改变了它们,所以它们会暂时显示出来。

一旦我将“B”资本化为“qazxswpoi”,问题就解决了。 我仍然不知道为什么它可以在我的本地机器和Dev中工作,但不在Prod中。 它应该在两种环境中表现相同。 同样,相同的服务器,相同的发布,相同的web.config,相同的iis配置,相同的应用程序代码等... 对不起,我对此没有解释,但至少这是一个可能的解决方案,你可以尝试。

希望这有助于那里的人。

更新02/08/2019:我再次遇到这个问题有一个不同的链接,对于这一个我意识到我有一个选项设置为当我的一个Debug变量设置为true或在Prod中运行时访问区域内的所有操作。我在AreaRegistration.cs文件中删除了这个条件逻辑,它解决了在Staging环境中运行时的问题。

这里的经验教训是,无论何时你看到一个空白的Href,你都要检查那些路径配置。

© www.soinside.com 2019 - 2024. All rights reserved.