我有一个Sitecore站点,在我的两个CD服务器上,Url.Action
返回一个空字符串。这适用于本地和其他9个服务器,从开发到产品,CD和CM。
部署自动化可确保将完全相同的web.config
部署到所有环境中;所有其他配置都同样如此。
我的控制器正确地从SitecoreController
继承。这不会与某个控制器或操作隔离,所有控制器和操作都会发生这种情况。
什么会使Url.Action
在一个环境中返回空字符串而不是其他环境中的相同代码?
答案 0 :(得分:6)
什么会让Url.Action有时会返回一个空字符串?
具体而言,路由从当前请求派生的值。
Url.Action
方法由UrlHelper
驱动,后者又由路由驱动。它使用路由值来确定用于构建URL的路由。路由框架尝试按照它们注册的顺序将每个路由与路由值进行匹配,直到找到匹配为止。如果路由框架到达路由表的末尾并且仍然没有匹配,则返回一个空字符串(因为没有其他合理的默认行为)。
另一方面,如果您呼叫Url.Action
并传递路由名称,则会将可能的匹配范围缩小到仅1个特定路由(命名路由)。但是路由值仍然需要匹配该路由,否则您将获得默认的空字符串。
通常,所有路线值必须匹配,但有一些事情可能会使行为古怪:
Url.Action
的来电中未提供路线值,则可能会自动提供如果当前请求中存在 。第二个怪癖意味着如果Url.Action
放在共享视图上,并且一个请求包含路由值以使其与路由匹配,而另一个请求不包含该路由值,则后者如果URL可能与另一条路线匹配,或者它可能是一个空字符串。
假设路由配置设置如下:
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" }
);
}
}
另外,我们假设_Layout.cshtml
页面上有一个链接:
<a href='@Url.Action("About", "Home")'>About</a>
如果您转到浏览器中的主页(/
),则生成的链接网址将为:
<a>About</a>
这是因为foo
和bar
不存在于请求的路由值中,因此它不匹配任何已注册的路由。
实际上,
Url.Action
会返回一个空字符串,但Razor会优化空的href=''
属性。
另一方面,如果您将此URL放在浏览器中:
/test/home/contact/arg1/arg2
链接网址生成为:
<a href='/test/home/about/arg1/arg2'>About</a>
这是因为当前请求中都有{foo}
(值arg1
)和{bar}
(值arg2
)。请注意,传入请求与ContactWith4RouteValues
路由匹配,但在生成链接URL时,它使用AboutWith4RouteValues
路由。由于请求中都包含foo
和bar
,因此会将其转移到URL的生成位置。
现在,如果浏览器中的URL更改为:
/test/home/contact/arg1
它仍匹配ContactWith4RouteValues
路由,因为最后一个值是可选的。但是,生成的URL现在是:
<a>About</a>
这是因为foo
在请求中有值,但bar
没有值,Url.Action
生成请求与AboutWith4RouteValues
不匹配,因为bar
是一个必需的值,以使其匹配。由于它也不匹配Home
路由,因此我们已经到达路由表的末尾,并且返回的唯一逻辑是空字符串。
避免当前请求的这些怪癖的最简单的解决方法是在调用Url.Action
或其他基于UrlHelper
的方法(例如{{1}时手动指定路由值 },ActionLink
等。)
RedirectToRoute
这可以确保在构建URL时始终存在这些值,即使它们不是当前请求的一部分。
答案 1 :(得分:0)
我遇到了完全相同的问题,对我来说,这个问题与我的路由中的区分大小写有关。
将同一站点部署到同一IIS Web服务器上的两个不同的应用程序。
我使用了相同的Web配置和VS Web发布设置。
但是,我的Url.Action
在Prod中返回了空白(空字符串),而在Dev中却没有。
在查看了代码之后,有什么引起了我的注意。
我有一个名为WorkBench
的区域(大写的“ B
”)。
在某些地方(Url.Action
返回空白),我传入了Workbench
(小写的“ b
”)。
我在RouteConfig.cs
和区域注册(即WorkBenchAreaRegistration.cs
)中有一些幻想。
在这些文件中,我使用条件逻辑来确定应用程序在哪个环境中运行。
我使用同一项目共享代码,但只希望在不同环境中访问某些区域。
即使Prod和Dev是不同的环境,也要调试此问题,
我更改了它们,以便它们暂时显示为相同。
在所有地方将大写字母“ b
大写为“ B
”后,该问题已解决。
我仍然不知道为什么它不能在我的本地计算机和Dev中工作,但是在Prod中不是。
在两个环境中,它应该具有相同的行为。
同样,相同的服务器,相同的发布,相同的web.config,相同的iis配置,相同的应用程序代码等...
抱歉,我对此没有任何解释,但是至少这是您可以尝试的解决方法。
希望这可以帮助某个人。
更新02/08/2019:我通过另一个链接再次遇到此问题,为此我意识到当我的一个Debug变量设置为true时,或者当我将一个Debug变量设置为true时,我已经设置了一个选项来访问区域内的所有操作在产品中运行。我在AreaRegistration.cs文件中删除了此条件逻辑,并解决了在暂存环境中运行时的问题。
这里的经验教训是,只要您看到空白的Href,就必须检查那些路由配置。