如何将MVCSiteMapProvider v4与Unity DI结合使用来配置多个站点地图 [英] How to configure multiple sitemaps using using MVCSiteMapProvider v4 with Unity DI

查看:59
本文介绍了如何将MVCSiteMapProvider v4与Unity DI结合使用来配置多个站点地图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究包含多个区域的ASP.NET MVC 4应用程序.根据项目要求,每个区域都应该有自己的站点地图文件.本文摘自: https://github.com/maartenba/MvcSiteMapProvider/wiki/Multiple-Sitemaps-in-One-Application ,我了解到,要使MvcSiteMapProvider与多个站点地图一起使用,必须使用外部DI.因此,我安装了软件包:MvcSiteMapProvider.MVC4.DI.Unity.Modules并根据本文修改了类MvcSiteMapProviderContainerExtension.每当我尝试建立菜单时,都会显示以下错误:

I am working on an ASP.NET MVC 4 application that contains multiple areas. As per project requirements each area should have its own sitemap file. From this article: https://github.com/maartenba/MvcSiteMapProvider/wiki/Multiple-Sitemaps-in-One-Application, I understand that in order to make MvcSiteMapProvider work with multiple sitemaps it is necessary to use an external DI. Therefore, I installed the package: MvcSiteMapProvider.MVC4.DI.Unity.Modules and modified the class MvcSiteMapProviderContainerExtension according to this article. Whenever I try to buid a menu the following error is being displayed:

有多个以上声明的没有父键的节点.必须为SiteMap中除1个节点以外的所有节点设置父键.没有父密钥的节点将被视为根节点.请注意,在用XML定义节点时,XML文件必须包含根节点.

There is more than one node declared without a parent key. The parent key must be set for all but 1 node in the SiteMap. The node with no parent key will be considered the root node. Note that when defining nodes in XML, the XML file must contain the root node.

您可以通过将MvcSiteMapProvider_EnableSiteMapFile设置设置为"false"来禁用XML配置.对于外部DI配置,可以通过从MvcSiteMapProvider DI模块中删除XmlSiteMapNodeProvider来禁用XML解析.

You can disable XML configuration by setting the MvcSiteMapProvider_EnableSiteMapFile setting to "false". For an external DI configuration, you can disable XML parsing by removing the XmlSiteMapNodeProvider from the MvcSiteMapProvider DI module.

或者,您可以将MvcSiteMapProvider_IncludeRootNodeFromSiteMapFile设置设置为"false".从XML文件中排除根节点,但包括所有其他节点.对于外部DI配置,可以在XmlSiteMapNodeProvider的构造函数中找到此设置.

Alternatively, you can set the MvcSiteMapProvider_IncludeRootNodeFromSiteMapFile setting to "false" to exclude the root node from the XML file, but include all of the other nodes. For an external DI configuration, this setting can be found on the constructor of the XmlSiteMapNodeProvider.

SiteMapCacheKey:'sitemap://admin/'

SiteMapCacheKey: 'sitemap://admin/'

歧义的根节点:

ParentKey:" |控制器:首页" |行动:索引" |区域:" |网址:"/" |关键字:'rootarea'|来源:.sitemap XML文件"

ParentKey: '' | Controller: 'Home' | Action: 'Index' | Area: '' | URL: '/' | Key: 'rootarea' | Source: '.sitemap XML File'

ParentKey:" |控制器:"AdminHome" |行动:索引" |区域:管理员" |网址:"/Admin/AdminHome" |关键字:"adminarea" |来源:.sitemap XML文件"

ParentKey: '' | Controller: 'AdminHome' | Action: 'Index' | Area: 'Admin' | URL: '/Admin/AdminHome' | Key: 'adminarea' | Source: '.sitemap XML File'

任何帮助将不胜感激.

如果您需要更多信息,请告诉我.

If you need further info please let me know.

推荐答案

已在 https:回答://github.com/maartenba/MvcSiteMapProvider/issues/237 .我在这里复制以供参考.

Already answered at https://github.com/maartenba/MvcSiteMapProvider/issues/237. I am copying here for reference.

这是在Unity中使用2个不同的 SiteMap 实例的示例.

Here is an example of using 2 different SiteMap instances with Unity.

    public class MvcSiteMapProviderContainerExtension
            : UnityContainerExtension
    {
        protected override void Initialize()
        {
            bool securityTrimmingEnabled = false;
            bool enableLocalization = true;

            string rootSiteMapFile = HostingEnvironment.MapPath("~/Mvc.sitemap");
            string adminSiteMapFile = HostingEnvironment.MapPath("~/Areas/Admin/Mvc.sitemap");

            TimeSpan absoluteCacheExpiration = TimeSpan.FromMinutes(5);
            string[] includeAssembliesForScan = new string[] { "MccSiteMapProviderTest" };

            var currentAssembly = this.GetType().Assembly;
            var siteMapProviderAssembly = typeof(SiteMaps).Assembly;
            var allAssemblies = new Assembly[] { currentAssembly, siteMapProviderAssembly };
            var excludeTypes = new Type[] {
                typeof(SiteMapNodeVisibilityProviderStrategy),
                typeof(SiteMapXmlReservedAttributeNameProvider),
                typeof(SiteMapBuilderSetStrategy),
                typeof(SiteMapNodeUrlResolverStrategy),
                typeof(DynamicNodeProviderStrategy)
            };
            var multipleImplementationTypes = new Type[] {
                typeof(ISiteMapNodeUrlResolver),
                typeof(ISiteMapNodeVisibilityProvider),
                typeof(IDynamicNodeProvider)
            };

    // Single implementations of interface with matching name (minus the "I").
            CommonConventions.RegisterDefaultConventions(
                (interfaceType, implementationType) => this.Container.RegisterType(interfaceType, implementationType, new ContainerControlledLifetimeManager()),
                new Assembly[] { siteMapProviderAssembly },
                allAssemblies,
                excludeTypes,
                string.Empty);

    // Multiple implementations of strategy based extension points
            CommonConventions.RegisterAllImplementationsOfInterface(
                (interfaceType, implementationType) => this.Container.RegisterType(interfaceType, implementationType, implementationType.Name, new ContainerControlledLifetimeManager()),
                multipleImplementationTypes,
                allAssemblies,
                excludeTypes,
                "^Composite");

    // TODO: Find a better way to inject an array constructor

    // Url Resolvers
            this.Container.RegisterType<ISiteMapNodeUrlResolverStrategy, SiteMapNodeUrlResolverStrategy>(new InjectionConstructor(
                new ResolvedArrayParameter<ISiteMapNodeUrlResolver>(this.Container.ResolveAll<ISiteMapNodeUrlResolver>().ToArray())
                ));

    // Visibility Providers
            this.Container.RegisterType<ISiteMapNodeVisibilityProviderStrategy, SiteMapNodeVisibilityProviderStrategy>(new InjectionConstructor(
                new ResolvedArrayParameter<ISiteMapNodeVisibilityProvider>(this.Container.ResolveAll<ISiteMapNodeVisibilityProvider>().ToArray()),
                new InjectionParameter<string>(string.Empty)
                ));

    // Dynamic Node Providers
            this.Container.RegisterType<IDynamicNodeProviderStrategy, DynamicNodeProviderStrategy>(new InjectionConstructor(
                new ResolvedArrayParameter<IDynamicNodeProvider>(this.Container.ResolveAll<IDynamicNodeProvider>().ToArray())
                ));


    // Pass in the global controllerBuilder reference
            this.Container.RegisterInstance<ControllerBuilder>(ControllerBuilder.Current);
            this.Container.RegisterType<IControllerBuilder, ControllerBuilderAdaptor>(new PerResolveLifetimeManager());

            this.Container.RegisterType<IBuildManager, BuildManagerAdaptor>(new PerResolveLifetimeManager());

            this.Container.RegisterType<IControllerTypeResolverFactory, ControllerTypeResolverFactory>(new InjectionConstructor(
                new List<string>(),
                new ResolvedParameter<IControllerBuilder>(),
                new ResolvedParameter<IBuildManager>()));

    // Configure Security

    // IMPORTANT: Must give arrays of object a name in Unity in order for it to resolve them.
            this.Container.RegisterType<IAclModule, AuthorizeAttributeAclModule>("authorizeAttribute");
            this.Container.RegisterType<IAclModule, XmlRolesAclModule>("xmlRoles");
            this.Container.RegisterType<IAclModule, CompositeAclModule>(new InjectionConstructor(new ResolvedArrayParameter<IAclModule>(
                new ResolvedParameter<IAclModule>("authorizeAttribute"),
                new ResolvedParameter<IAclModule>("xmlRoles"))));



            this.Container.RegisterType<ISiteMapCacheKeyGenerator, SiteMapCacheKeyGenerator2>();


            this.Container.RegisterInstance<System.Runtime.Caching.ObjectCache>(System.Runtime.Caching.MemoryCache.Default);
            this.Container.RegisterType(typeof(ICacheProvider<>), typeof(RuntimeCacheProvider<>));

            this.Container.RegisterType<ICacheDependency, RuntimeFileCacheDependency>(
                "rootSiteMapCacheDependency", new InjectionConstructor(rootSiteMapFile));

            this.Container.RegisterType<ICacheDependency, RuntimeFileCacheDependency>(
                "adminSiteMapCacheDependency", new InjectionConstructor(adminSiteMapFile));

            this.Container.RegisterType<ICacheDetails, CacheDetails>("rootSiteMapCacheDetails",
                new InjectionConstructor(absoluteCacheExpiration, TimeSpan.MinValue, new ResolvedParameter<ICacheDependency>("rootSiteMapCacheDependency")));

            this.Container.RegisterType<ICacheDetails, CacheDetails>("adminSiteMapCacheDetails",
                new InjectionConstructor(absoluteCacheExpiration, TimeSpan.MinValue, new ResolvedParameter<ICacheDependency>("adminSiteMapCacheDependency")));

// Configure the visitors
            this.Container.RegisterType<ISiteMapNodeVisitor, UrlResolvingSiteMapNodeVisitor>();

// Prepare for the sitemap node providers
            this.Container.RegisterType<IXmlSource, FileXmlSource>("rootSiteMapXmlSource", new InjectionConstructor(rootSiteMapFile));
            this.Container.RegisterType<IXmlSource, FileXmlSource>("adminSiteMapXmlSource", new InjectionConstructor(adminSiteMapFile));

    // IMPORTANT: Must give arrays of object a name in Unity in order for it to resolve them.
    // Register the sitemap node providers
        this.Container.RegisterInstance<ISiteMapNodeProvider>("rootXmlSiteMapNodeProvider",
            this.Container.Resolve<XmlSiteMapNodeProviderFactory>().Create(this.Container.Resolve<IXmlSource>("rootSiteMapXmlSource")), new ContainerControlledLifetimeManager());

        this.Container.RegisterInstance<ISiteMapNodeProvider>("adminXmlSiteMapNodeProvider",
            this.Container.Resolve<XmlSiteMapNodeProviderFactory>().Create(this.Container.Resolve<IXmlSource>("adminSiteMapXmlSource")), new ContainerControlledLifetimeManager());

        this.Container.RegisterInstance<ISiteMapNodeProvider>("ReflectionSiteMapNodeProvider1",
            this.Container.Resolve<ReflectionSiteMapNodeProviderFactory>().Create(includeAssembliesForScan), new ContainerControlledLifetimeManager());

        this.Container.RegisterType<ISiteMapNodeProvider, CompositeSiteMapNodeProvider>("rootSiteMapNodeProvider", 
            new ContainerControlledLifetimeManager(),
            new InjectionConstructor(new ResolvedArrayParameter<ISiteMapNodeProvider>(
                new ResolvedParameter<ISiteMapNodeProvider>("rootXmlSiteMapNodeProvider"),
                new ResolvedParameter<ISiteMapNodeProvider>("ReflectionSiteMapNodeProvider1"))));

        this.Container.RegisterType<ISiteMapNodeProvider, CompositeSiteMapNodeProvider>("adminSiteMapNodeProvider",
            new ContainerControlledLifetimeManager(),
            new InjectionConstructor(new ResolvedArrayParameter<ISiteMapNodeProvider>(
                new ResolvedParameter<ISiteMapNodeProvider>("adminXmlSiteMapNodeProvider"),
                new ResolvedParameter<ISiteMapNodeProvider>("ReflectionSiteMapNodeProvider1"))));

    // Configure the builders
        this.Container.RegisterInstance<ISiteMapBuilder>("rootSiteMapBuilder", 
            this.Container.Resolve<SiteMapBuilderFactory>().Create(this.Container.Resolve<ISiteMapNodeProvider>("rootSiteMapNodeProvider")), 
            new ContainerControlledLifetimeManager());

        this.Container.RegisterInstance<ISiteMapBuilder>("adminSiteMapBuilder", 
            this.Container.Resolve<SiteMapBuilderFactory>().Create(this.Container.Resolve<ISiteMapNodeProvider>("adminSiteMapNodeProvider")), 
            new ContainerControlledLifetimeManager());      

    // Configure the builder sets
        this.Container.RegisterType<ISiteMapBuilderSet, SiteMapBuilderSet>("rootBuilderSet",
            new InjectionConstructor(
                "default",
                securityTrimmingEnabled,
                enableLocalization,
                new ResolvedParameter<ISiteMapBuilder>("rootSiteMapBuilder"),
                new ResolvedParameter<ICacheDetails>("rootSiteMapCacheDetails")));

        this.Container.RegisterType<ISiteMapBuilderSet, SiteMapBuilderSet>("adminBuilderSet",
            new InjectionConstructor(
                "admin",
                securityTrimmingEnabled,
                enableLocalization,
                new ResolvedParameter<ISiteMapBuilder>("adminSiteMapBuilder"),
                new ResolvedParameter<ICacheDetails>("adminSiteMapCacheDetails")));
        }
    }

请注意,有一些工厂称为 SiteMapBuilderFactory XmlSiteMapNodeProviderFactory ReflectionSiteMapNodeProviderFactory ,这些工厂特定于Unity和其他不允许的DI容器您可以插入单个对象,而不必绑定到在这种情况下应使用的构造函数签名.这将有助于确保将来发生的更改数量最少,因为构造函数签名可能会随时间变化.

Note that there are factories called SiteMapBuilderFactory, XmlSiteMapNodeProviderFactory, and ReflectionSiteMapNodeProviderFactory that are specific to Unity and other DI containers that don't allow you to insert individual objects without binding to the constructor signature that should be used in this case. This will help ensure minimal number of future changes as the constructor signature is likely to change over time.

这篇关于如何将MVCSiteMapProvider v4与Unity DI结合使用来配置多个站点地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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