怎样使MvcSiteMapProvider每创造1区网站地图? [英] How do I make MvcSiteMapProvider create 1 SiteMap per Area?

查看:286
本文介绍了怎样使MvcSiteMapProvider每创造1区网站地图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你如何让每MVC区1网站地图,并在同一时间使用MvcSiteMapNodeAttribute?

How do you make 1 SiteMap per MVC area and use MvcSiteMapNodeAttribute at the same time?

推荐答案

请看看的这个答案的帮助与地区建立MvcSiteMapProvider。这些路线都必须使用正确的约定进行配置,否则将无法正常工作。

Please have a look at this answer for help with setting up MvcSiteMapProvider with areas. The routes have to be configured using the correct conventions or it won't work right.

不过,单靠不会满足这一要求,因为没有默认的假设下进行的,你想有单位面积不同的地图。

However, that alone isn't going to address this requirement, because there is no default assumption made that you want to have a different SiteMap per area.

内部DI容器的行为假定会有每域名1网站地图,并且所有应用程序中的SiteMaps的将使用相同​​的配置来构建。没有办法,除非你使用一个外部的DI容器来改变这种行为,并遵循的 =nofollow的>多个站点地图覆盖它。

The behavior of the internal DI container assumes that there will be 1 SiteMap per domain name, and that all of the SiteMaps in the application will be built using the same configuration. There is no way to change this behavior unless you use an external DI container and follow the instructions in Multiple SiteMaps in One Application to override it.

您可以继续使用内部DI容器和整个网站的一个网站地图,你可以创建一个自定义的 ISiteMapNodeVisibilityProvider 隐藏一切不是在当前区域通过从当前请求读取的区域。

You could continue using the internal DI container and a single SiteMap for the entire website and you could create a custom ISiteMapNodeVisibilityProvider that hides everything that is not in the current area by reading the area from the current request.

public class AreaSiteMapNodeVisibilityProvider
    : SiteMapNodeVisibilityProviderBase
{
    public AreaSiteMapNodeVisibilityProvider()
    {
        // NOTE: Accept this as a constructor parameter if using external DI and 
        // use a guard clause to ensure it is not null.
        this.mvcContextFactory = new MvcSiteMapProvider.Web.Mvc.MvcContextFactory();
    }
    private readonly MvcSiteMapProvider.Web.Mvc.IMvcContextFactory mvcContextFactory;

    #region ISiteMapNodeVisibilityProvider Members

    public override bool IsVisible(ISiteMapNode node, IDictionary<string, object> sourceMetadata)
    {
        var requestContext = this.mvcContextFactory.CreateRequestContext();
        var area = requestContext.RouteData.DataTokens["area"];
        var areaName = area == null ? string.Empty : area.ToString();
        return string.Equals(node.Area, areaName, StringComparison.OrdinalIgnoreCase);
    }

    #endregion
}

然后将其设置为默认的可见性提供者。

Then set it up as the default visibility provider.

<add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MyNameSpace.AreaSiteMapNodeVisibilityProvider, MyAssemblyName" />

使用外部DI(StructureMap的例子所示):

Using external DI (StructureMap example shown):

// Visibility Providers
this.For<ISiteMapNodeVisibilityProviderStrategy>().Use<SiteMapNodeVisibilityProviderStrategy>()
    .Ctor<string>("defaultProviderName").Is("MyNameSpace.AreaSiteMapNodeVisibilityProvider, MyAssemblyName");

请注意,您仍然需要鸟巢网站的非区域部分下方的区域节点,如果你这样做,所以它可能不会像你想。你需要确保你的管理区域的父项设置为在非区域部分节点的关键 - 只能有每个站点地图1根节点

Do note that you will still need to nest your area nodes below the non-area part of the site if you do this, so it might not behave as you would like. You need to ensure you set the parent key of the Admin area to a key of a node in the non-area part - there can only be 1 root node per SiteMap.

另外,如果你走这条路线,一定要设置<一个href=\"https://github.com/maartenba/MvcSiteMapProvider/wiki/Configuring-MvcSiteMapProvider#mvcsitemapprovider_visibilityaffectsdescendants\"相对=nofollow> MvcSiteMapProvider_VisibilityAffectsDescendants 设置为假,让您所在地区的节点不会受到非区域节点的可见性。

Also, if you go this route, be sure to set the MvcSiteMapProvider_VisibilityAffectsDescendants setting to "false" so your area nodes are not affected by the visibility of the non-area nodes.

注入是基于区域定制ISiteMapCacheKeyGenerator和使用[MvcSiteMapNode]的SiteMapCacheKey属性的属性来控制所述节点所属的区域。

Inject a custom ISiteMapCacheKeyGenerator that is based on area and use the SiteMapCacheKey property of [MvcSiteMapNode] attribute to control which area the node belongs to.

public class AreaSiteMapCacheKeyGenerator
    : ISiteMapCacheKeyGenerator
{
    public AreaSiteMapCacheKeyGenerator(
        IMvcContextFactory mvcContextFactory
        )
    {
        if (mvcContextFactory == null)
            throw new ArgumentNullException("mvcContextFactory");
        this.mvcContextFactory = mvcContextFactory;
    }

    protected readonly IMvcContextFactory mvcContextFactory;

    #region ISiteMapCacheKeyGenerator Members

    public virtual string GenerateKey()
    {
        var requestContext = this.mvcContextFactory.CreateRequestContext();
        var area = requestContext.RouteData.DataTokens["area"];
        return area == null ? "default" : area.ToString();
    }

    #endregion
}

您需要注入这样使用外部DI(如图StructureMap为例):

You need to inject this using external DI (StructureMap example shown):

this.For<ISiteMapCacheKeyGenerator>().Use<AreaSiteMapCacheKeyGenerator>();

然后配置你的[MvcSiteMapNode]属性:

And then configure your [MvcSiteMapNode] attributes:

[MvcSiteMapNode(Title = "title", Description = "desc", Key = "root", ParentKey = null, ImageUrl = "fa-home", Order = 0, SiteMapCacheKey = "Admin")]
[MvcSiteMapNode(Title = "title", Description = "desc", Key = "root", ParentKey = null, ImageUrl = "fa-home", Order = 0, SiteMapCacheKey = "default")]

选项3

而不是在每一个[MvcSiteMapNode]属性设置SiteMapCacheKey,你可以把每个区域在单独的程序,并将其配置为仅扫描[MvcSiteMapNode]相关区域集属性。

Option 3

Rather than setting SiteMapCacheKey on every [MvcSiteMapNode] attribute, you could put each area in a separate assembly and configure it to only scan the pertinent area assembly for [MvcSiteMapNode] attribute.

public class AreaSiteMapCacheKeyGenerator
    : ISiteMapCacheKeyGenerator
{
    public AreaSiteMapCacheKeyGenerator(
        IMvcContextFactory mvcContextFactory
        )
    {
        if (mvcContextFactory == null)
            throw new ArgumentNullException("mvcContextFactory");
        this.mvcContextFactory = mvcContextFactory;
    }

    protected readonly IMvcContextFactory mvcContextFactory;

    #region ISiteMapCacheKeyGenerator Members

    public virtual string GenerateKey()
    {
        var requestContext = this.mvcContextFactory.CreateRequestContext();
        var area = requestContext.RouteData.DataTokens["area"];
        return area == null ? "default" : area.ToString();
    }

    #endregion
}

public class OneToOneSiteMapCacheKeyToBuilderSetMapper
    : ISiteMapCacheKeyToBuilderSetMapper
{
    public virtual string GetBuilderSetName(string cacheKey)
    {
        return cacheKey;
    }
}

在外部DI模块(如图StructureMap为例):

In the external DI module (StructureMap example shown):

// Setup the cache
var cacheDependency = this.For<ICacheDependency>().Use<NullCacheDependency>();

var cacheDetails = this.For<ICacheDetails>().Use<CacheDetails>()
    .Ctor<TimeSpan>("absoluteCacheExpiration").Is(absoluteCacheExpiration)
    .Ctor<TimeSpan>("slidingCacheExpiration").Is(TimeSpan.MinValue)
    .Ctor<ICacheDependency>().Is(cacheDependency);

// Register the ISiteMapNodeProvider instances
var defaultNodeProvider = this.For<ISiteMapNodeProvider>().Use<ReflectionSiteMapNodeProvider>()
    .Ctor<bool>("includeAssemblies").Is(new string[] { "dllmain" });

var adminNodeProvider = this.For<ISiteMapNodeProvider>().Use<ReflectionSiteMapNodeProvider>()
    .Ctor<bool>("includeAssemblies").Is(new string[] { "dll2" });

// Register the ISiteMapBuilder instances
var defaultBuilder = this.For<ISiteMapBuilder>().Use<SiteMapBuilder>()
    .Ctor<ISiteMapNodeProvider>().Is(defaultNodeProvider);

var adminBuilder = this.For<ISiteMapBuilder>().Use<SiteMapBuilder>()
    .Ctor<ISiteMapNodeProvider>().Is(adminNodeProvider);

// Register the builder sets
this.For<ISiteMapBuilderSetStrategy>().Use<SiteMapBuilderSetStrategy>()
    .EnumerableOf<ISiteMapBuilderSet>().Contains(x =>
    {
        // SiteMap builder for the non-area part of the site
        x.Type<SiteMapBuilderSet>()
            .Ctor<string>("instanceName").Is("default")
            .Ctor<bool>("securityTrimmingEnabled").Is(false)
            .Ctor<bool>("enableLocalization").Is(false)
            .Ctor<bool>("visibilityAffectsDescendants").Is(false)
            .Ctor<bool>("useTitleIfDescriptionNotProvided").Is(true)
            .Ctor<ISiteMapBuilder>().Is(defaultBuilder)
            .Ctor<ICacheDetails>().Is(cacheDetails);

        // SiteMap builder for the Admin area of the site
        x.Type<SiteMapBuilderSet>()
            .Ctor<string>("instanceName").Is("Admin")
            .Ctor<bool>("securityTrimmingEnabled").Is(false)
            .Ctor<bool>("enableLocalization").Is(false)
            .Ctor<bool>("visibilityAffectsDescendants").Is(false)
            .Ctor<bool>("useTitleIfDescriptionNotProvided").Is(true)
            .Ctor<ISiteMapBuilder>().Is(adminBuilder)
            .Ctor<ICacheDetails>().Is(cacheDetails);
    });

// Register the custom ISiteMapCacheKeyGenerator and ISiteMapCacheKeyToBuilderSetMapper
this.For<ISiteMapCacheKeyGenerator>().Use<AreaSiteMapCacheKeyGenerator>();
this.For<ISiteMapCacheKeyToBuilderSetMapper>().Use<OneToOneSiteMapCacheKeyToBuilderSetMapper>();

这篇关于怎样使MvcSiteMapProvider每创造1区网站地图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆