MVCSiteMapProvider面包屑没有正确返回链接

时间:2015-09-29 15:05:28

标签: asp.net-mvc asp.net-mvc-4 breadcrumbs mvcsitemapprovider

MVC Sitemap Provider版本4.6.18.0(程序集版本) 使用MVC4

我已经设置了一些带有动态节点的静态根节点的站点地图,用于显示单个产品项目。为简洁起见,我们假设有两种产品类型

1)新娘 2)珠宝

每种产品类型都有与之关联的Band类型。 问题: 我在Mvc.sitemap中首先列出了Bridal,它似乎优先于breadcrumb显示,因此相对于面包屑的反向链接不正确。

    <mvcSiteMapNode title="Bridal" controller="Products" action="Bridal">
        <mvcSiteMapNode title="Bands" controller="Products"  action="BridalRings">
            <mvcSiteMapNode title="Details" action="BridalRings" key="Bands" dynamicNodeProvider="Betteridge.Web.Services.ProductNodeProvider, Betteridge.Web" />
        </mvcSiteMapNode>
        <mvcSiteMapNode title="Engagement" controller="Products"  action="BridalEngagement">
            <mvcSiteMapNode title="Details" action="BridalEngagement" key="Engagement" dynamicNodeProvider="Betteridge.Web.Services.ProductNodeProvider, Betteridge.Web" />
        </mvcSiteMapNode>
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Jewelry" controller="Products" action="Jewelry">
        <mvcSiteMapNode title="Bands" controller="Products"  action="JewelryBands">
            <mvcSiteMapNode title="Details" action="JewelryBands" key="Bands" dynamicNodeProvider="Betteridge.Web.Services.ProductNodeProvider, Betteridge.Web" />
        </mvcSiteMapNode>

...

Jewelry Item displayed correctly with correct back links in breadcrumbs 如果我点击文字查看项目的更多细节,面包屑从珠宝变为新娘。

Changes from Jewelry To Bridal in crumb trail

为什么?

这是我的动态节点提供程序代码。

public class ProductNodeProvider : DynamicNodeProviderBase
{     
    public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
    {
        string parent = "";
        if(node.Attributes.ContainsKey("parentNode")) 
        {
            parent = node.Attributes["parentNode"].ToString(); 
        } 
        List<ProductModel> products = DataServices.GetActiveProductBySubType(parent,node.Key);


        var returnValue = new List<DynamicNode>(); 
        foreach (ProductModel p in products)
        {
            DynamicNode dnode = new DynamicNode();
            dnode.Title = p.ProductName;
            dnode.Action = "Details";
            dnode.Controller = "Products";
            dnode.RouteValues.Add("id", p.ProductId);

            returnValue.Add(dnode);
        } 
        return returnValue;
    }
}

我知道这一定是我要忽视的简单事情。任何帮助都会很棒。

2 个答案:

答案 0 :(得分:0)

  

为什么?

MvcSiteMapProvider 不支持具有相同路由值的多个节点

您需要为其添加至少一个附加参数,以区分Bridal下列出的产品与Jewelry下列出的产品之间的区别。

最简单的方法是简单地将此信息添加到路线中。

routes.MapRoute(
    name: "Category",
    url: "{controller}/{category}/{action}/{id}"
);

routes.MapRoute(
    name: "Default",
    url: "{controller}/{action}/{id}",
    defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);

然后您只需要将category参数添加到动态节点。最简单的方法是将其添加到XML中,它将自动作为路由值包含在提供者创建的每个动态节点中。

<mvcSiteMapNode title="Bridal" controller="Products" action="Bridal">
    <mvcSiteMapNode title="Bands" controller="Products"  action="BridalRings">
        <mvcSiteMapNode title="Details" action="BridalRings" key="Bands" category="BridalRings" dynamicNodeProvider="Betteridge.Web.Services.ProductNodeProvider, Betteridge.Web" />
    </mvcSiteMapNode>
    <mvcSiteMapNode title="Engagement" controller="Products"  action="BridalEngagement">
        <mvcSiteMapNode title="Details" action="BridalEngagement" key="Engagement" category="BridalEngagement" dynamicNodeProvider="Betteridge.Web.Services.ProductNodeProvider, Betteridge.Web" />
    </mvcSiteMapNode>
</mvcSiteMapNode>
<mvcSiteMapNode title="Jewelry" controller="Products" action="Jewelry">
    <mvcSiteMapNode title="Bands" controller="Products"  action="JewelryBands">
        <mvcSiteMapNode title="Details" action="JewelryBands" key="Bands" category="JewelryBands" dynamicNodeProvider="Betteridge.Web.Services.ProductNodeProvider, Betteridge.Web" />
    </mvcSiteMapNode>
</mvcSiteMapNode>

修复SEO

确实,将相同的内容放在2个不同的网址上是件坏事 - 也就是说,直到您添加canonical tag来指示哪一个是&#34;主要&#34;内容来源。这就是你可以向搜索引擎表明这是内容的故意副本。

MvcSiteMapProvider只需指定canonicalKey即可支持规范标记生成。您只需要确保有一个唯一的密钥给予&#34; master&#34;节点,然后对所有副本使用相同的密钥。

要启用规范密钥生成,您只需将CanonicalTag HTML帮助器添加到_Layout.cshtml页面(<head>元素内)。

@Html.MvcSiteMap().CanonicalTag()

就您的网站设计而言,最好是您有某种方式来指明哪个类别是&#34;主要&#34;数据库中的一个,并执行适当的连接以确保正确设置密钥和规范密钥。

我创建了一个demo project,只是将规范键设置为BridalRings类别下的相应产品,以便您可以看到它是如何完成的。请注意,如果您转到其他类别下的产品详情并查看来源,则会看到一个规范标记,其中包含对原始内容网址的引用。

<link rel="canonical" href="http://localhost:64658/Products/BridalRings/Details/1" />

参考:https://github.com/maartenba/MvcSiteMapProvider/wiki/Multiple-Navigation-Paths-to-a-Single-Page

答案 1 :(得分:0)

有两个问题。 1)创建不同的路径以清楚地识别由@ nightOwl888提供的示例应用程序中定义的产品类型。 2)在站点地图定义中有一个属性“key”,它必须是唯一的,所以我已经学会了。我使用密钥来定义子产品类型,当您有重复的子产品类型时,这将产生冲突并且第一个定义获胜。

我是如何解决这个问题的 1)我创建了一个名为code的附加属性。此代码可以在整个站点地图中重复。这允许我为父类别传递重复的子类型。

2)现在我在整个工作面包屑。