0

我正在研究包含多個區域的ASP.NET MVC 4應用程序。按照項目要求,每個區域應該有自己的站點地圖文件。 從這篇文章:https://github.com/maartenba/MvcSiteMapProvider/wiki/Multiple-Sitemaps-in-One-Application,我明白,爲了使MvcSiteMapProvider與多個站點地圖工作,有必要使用外部DI。因此,我安裝了包:MvcSiteMapProvider.MVC4.DI.Unity.Modules,並根據本文修改了類MvcSiteMapProviderContainerExtension。每當我嘗試構建菜單時,都會顯示以下錯誤:如何在Unity DI中使用MVCSiteMapProvider v4配置多個站點地圖

在沒有父鍵的情況下聲明瞭多個節點。父密鑰必須設置爲SiteMap中除1個節點以外的所有節點。沒有父鍵的節點將被視爲根節點。請注意,在XML中定義節點時,XML文件必須包含根節點。

您可以通過將MvcSiteMapProvider_EnableSiteMapFile設置爲「false」來禁用XML配置。對於外部DI配置,您可以通過從MvcSiteMapProvider DI模塊中刪除XmlSiteMapNodeProvider來禁用XML解析。

或者,您可以將MvcSiteMapProvider_IncludeRootNodeFromSiteMapFile設置爲「false」,以從XML文件中排除根節點,但包括所有其他節點。對於外部DI配置,可以在XmlSiteMapNodeProvider的構造函數中找到此設置。

SiteMapCacheKey: '網站地圖://管理/'

曖昧根節點:

ParentKey: '' |控制器:'主頁'|行動:'索引'|區域:''|網址:'/'|鍵:'rootarea'|資料來源:'.sitemap XML File'

ParentKey:''|控制器:'AdminHome'|行動:'索引'|區域:'管理員'|網址:'/ Admin/AdminHome'|鍵:'adminarea'|來源:'.sitemap XML文件'

任何幫助將不勝感激。

如果您需要更多信息,請讓我知道。

回答

2

已經在https://github.com/maartenba/MvcSiteMapProvider/issues/237回答。我在這裏複製以供參考。

以下是在Unity中使用2個不同SiteMap實例的示例。

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"))); 
     } 
    } 

注意,有工廠叫SiteMapBuilderFactoryXmlSiteMapNodeProviderFactory,並且ReflectionSiteMapNodeProviderFactory所特有的團結和其他DI容器不允許你插入單個對象而不結合應該在這個被用來構造簽名案件。這將有助於確保將來更改的次數最少,因爲構造函數簽名可能會隨時間而改變。

相關問題