MvcSiteMapProvider如何让一个节点匹配当前url
MvcSiteMapProvider how to make a node match the current url
当前节点为空。我不知道如何让 MvcSiteMapProvider 在这种情况下解析节点。
这是它需要匹配的节点
<mvcSiteMapNode title="Policy" route="Details" typeName="Biz.ABC.ShampooMax.Policy" preservedRouteParameters="id" />
路线如下:
routes.MapRoute(
"Details",
"Details/{id}",
new { Controller = "Object", Action = "Details" }
).RouteHandler = new ObjectRouteHandler();
被点击的link:
http://localhost:36695/MyGreatWebSite/Details/121534455762071
路线正常。只是 MvcSiteMapProvider.SiteMaps.Current.CurrentNode
为空。
CurrentNode
的 null
结果表明传入请求与 SiteMap
中的任何节点都不匹配在您的情况下,有 4 个不同的问题可能导致此问题:
- 您正在输入
http://localhost:36695/MyGreatWebSite/Details/121534455762071
的 URL 不(必然)匹配您在路由 "Details/{id}"
中指定的 URL 模式。如果您的站点作为 IIS 应用程序托管在 IISROOT/MyGreatWebSite/
. 下,则可能会出现这种情况
- 您的
mvcSiteMapNode
没有指定要匹配的 controller
或 action
。 route
只是一个额外的条件(意味着匹配中只会考虑指定的路由),但还需要提供所有参数才能与路由匹配。
- 您正在传递自定义
RouteHandler
,这可能会改变路由与 URL 匹配的方式。如果没有看到您的 ObjectRouteHandler
中的代码,则无法判断这是否或如何影响路由与 URL. 的匹配方式
- 您的
mvcSiteMapNode
配置中有一个自定义属性 typeName
。除非你指定为ignore this attribute,否则在URL中也需要匹配,即http://localhost:36695/MyGreatWebSite/Details/121534455762071?typeName=Biz.ABC.ShampooMax.Policy
.
我建议不要使用自定义 RouteHandler
来匹配 URL。这样做的效果会使您的传入路由(URLs 进入 MVC)与您的传出路由(URLs 生成到 link 到其他页面)行为不同。由于 MvcSiteMapProvider
使用路由的两个部分,如果您只更改传入路由而不同时更改传出路由以匹配,将导致 URL 生成问题。相反,我建议您子类化 RouteBase
,您可以在其中控制路线的两侧。有关自定义 RouteBase
子类的示例,请参阅 。
但是,请注意,常规路由非常强大,开箱即用,对于这个简单的场景,您可能不需要子类化 RouteBase
。
解决方案
我通过将 mvc 站点地图提供程序项目添加到我自己的解决方案中并单步执行 mvc 站点地图提供程序代码以查看为什么我的节点不匹配来找到答案。有几件事必须改变。我通过执行以下操作修复了它:
Mvc.sitemap
<mvcSiteMapNode title="Policy" controller="Object" action="Details" typeName="Biz.ABC.ShampootMax.Policy" preservedRouteParameters="id" roles="*"/>
RouteConfig.cs
routes.MapRoute(
name: "Details",
url: "details/{id}",
defaults: new { controller = "Object", action = "Details", typeName = "*" }
).RouteHandler = new ObjectRouteHandler();
现在一开始它不想这样工作,但我这样修改了提供者:
RouteValueDictionary.cs(添加通配符以匹配值)
protected virtual bool MatchesValue(string key, object value)
{
return this[key].ToString().Equals(value.ToString(), StringComparison.OrdinalIgnoreCase) || value.ToString() == "*";
}
SiteMapNode.cs(已更改 requestContext.RouteData.Values
)
/// <summary>
/// Sets the preserved route parameters of the current request to the routeValues collection.
/// </summary>
/// <remarks>
/// This method relies on the fact that the route value collection is request cached. The
/// values written are for the current request only, after which they will be discarded.
/// </remarks>
protected virtual void PreserveRouteParameters()
{
if (this.PreservedRouteParameters.Count > 0)
{
var requestContext = this.mvcContextFactory.CreateRequestContext();
var routeDataValues = requestContext.HttpContext.Request.RequestContext.RouteData.Values;// requestContext.RouteData.Values;
我认为第二次修改不是绝对必要的,因为我的请求上下文没有被缓存;如果是的话,它会起作用的。我不知道如何缓存它。
这是第一个使路由值支持通配符 (*) 的修改。这似乎是一个 hack,也许有一个内置的方式。
备注
忽略 typeName 属性:
web.config
<add key="MvcSiteMapProvider_AttributesToIgnore" value="typeName" />
使另一个节点中断:
Mvc.sitemap
<mvcSiteMapNode title="Policies" url="~/Home/Products/HarvestMAX/Policy/List" productType="HarvestMax" type="P" typeName="AACOBusinessModel.AACO.HarvestMax.Policy" roles="*">
所以这就是我没有这样做的原因。
当前节点为空。我不知道如何让 MvcSiteMapProvider 在这种情况下解析节点。
这是它需要匹配的节点
<mvcSiteMapNode title="Policy" route="Details" typeName="Biz.ABC.ShampooMax.Policy" preservedRouteParameters="id" />
路线如下:
routes.MapRoute(
"Details",
"Details/{id}",
new { Controller = "Object", Action = "Details" }
).RouteHandler = new ObjectRouteHandler();
被点击的link:
http://localhost:36695/MyGreatWebSite/Details/121534455762071
路线正常。只是 MvcSiteMapProvider.SiteMaps.Current.CurrentNode
为空。
CurrentNode
的 null
结果表明传入请求与 SiteMap
中的任何节点都不匹配在您的情况下,有 4 个不同的问题可能导致此问题:
- 您正在输入
http://localhost:36695/MyGreatWebSite/Details/121534455762071
的 URL 不(必然)匹配您在路由"Details/{id}"
中指定的 URL 模式。如果您的站点作为 IIS 应用程序托管在IISROOT/MyGreatWebSite/
. 下,则可能会出现这种情况
- 您的
mvcSiteMapNode
没有指定要匹配的controller
或action
。route
只是一个额外的条件(意味着匹配中只会考虑指定的路由),但还需要提供所有参数才能与路由匹配。 - 您正在传递自定义
RouteHandler
,这可能会改变路由与 URL 匹配的方式。如果没有看到您的ObjectRouteHandler
中的代码,则无法判断这是否或如何影响路由与 URL. 的匹配方式
- 您的
mvcSiteMapNode
配置中有一个自定义属性typeName
。除非你指定为ignore this attribute,否则在URL中也需要匹配,即http://localhost:36695/MyGreatWebSite/Details/121534455762071?typeName=Biz.ABC.ShampooMax.Policy
.
我建议不要使用自定义 RouteHandler
来匹配 URL。这样做的效果会使您的传入路由(URLs 进入 MVC)与您的传出路由(URLs 生成到 link 到其他页面)行为不同。由于 MvcSiteMapProvider
使用路由的两个部分,如果您只更改传入路由而不同时更改传出路由以匹配,将导致 URL 生成问题。相反,我建议您子类化 RouteBase
,您可以在其中控制路线的两侧。有关自定义 RouteBase
子类的示例,请参阅
但是,请注意,常规路由非常强大,开箱即用,对于这个简单的场景,您可能不需要子类化 RouteBase
。
解决方案
我通过将 mvc 站点地图提供程序项目添加到我自己的解决方案中并单步执行 mvc 站点地图提供程序代码以查看为什么我的节点不匹配来找到答案。有几件事必须改变。我通过执行以下操作修复了它:
Mvc.sitemap
<mvcSiteMapNode title="Policy" controller="Object" action="Details" typeName="Biz.ABC.ShampootMax.Policy" preservedRouteParameters="id" roles="*"/>
RouteConfig.cs
routes.MapRoute(
name: "Details",
url: "details/{id}",
defaults: new { controller = "Object", action = "Details", typeName = "*" }
).RouteHandler = new ObjectRouteHandler();
现在一开始它不想这样工作,但我这样修改了提供者:
RouteValueDictionary.cs(添加通配符以匹配值)
protected virtual bool MatchesValue(string key, object value)
{
return this[key].ToString().Equals(value.ToString(), StringComparison.OrdinalIgnoreCase) || value.ToString() == "*";
}
SiteMapNode.cs(已更改 requestContext.RouteData.Values
)
/// <summary>
/// Sets the preserved route parameters of the current request to the routeValues collection.
/// </summary>
/// <remarks>
/// This method relies on the fact that the route value collection is request cached. The
/// values written are for the current request only, after which they will be discarded.
/// </remarks>
protected virtual void PreserveRouteParameters()
{
if (this.PreservedRouteParameters.Count > 0)
{
var requestContext = this.mvcContextFactory.CreateRequestContext();
var routeDataValues = requestContext.HttpContext.Request.RequestContext.RouteData.Values;// requestContext.RouteData.Values;
我认为第二次修改不是绝对必要的,因为我的请求上下文没有被缓存;如果是的话,它会起作用的。我不知道如何缓存它。
这是第一个使路由值支持通配符 (*) 的修改。这似乎是一个 hack,也许有一个内置的方式。
备注
忽略 typeName 属性:
web.config
<add key="MvcSiteMapProvider_AttributesToIgnore" value="typeName" />
使另一个节点中断:
Mvc.sitemap
<mvcSiteMapNode title="Policies" url="~/Home/Products/HarvestMAX/Policy/List" productType="HarvestMax" type="P" typeName="AACOBusinessModel.AACO.HarvestMax.Policy" roles="*">
所以这就是我没有这样做的原因。