1

MVC4, MvcSiteMapProvider v3.2.1 (v4로 업그레이드 할 수 있음)을 사용하고 있습니다.여러 개의 하위 사이트 맵으로 사이트 맵을 구성하는 방법은 무엇입니까?

내 문제는 응용 프로그램이 큰 것입니다. 그리고 어플리케이션을 모듈화하고 모듈을 플러그 가능하게 만들고 싶습니다.
사이트 맵이 이미 거대하기 때문에 사이트 맵도 pluggalbe로 만들고 싶습니다.
응용 프로그램이 시작될 때 여러 xml 파일에서 노드를로드하는 루트 사이트 맵으로 사이트 맵을 구성하는 방법이 있습니까?
원래 사이트 맵 : 여기

설명하는 예입니다

<?xml version="1.0" encoding="utf-8" ?> 
<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0" 
      xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0 MvcSiteMapSchema.xsd" 
      enableLocalization="true"> 

    <mvcSiteMapNode title="Home" controller="Home" action="Index"> 

    <mvcSiteMapNode title="Staff List" controller="Staff" action="List"> 
     <mvcSiteMapNode title="Create Staff" controller="Staff" action="Create"/> 
     <mvcSiteMapNode title="Edit Staff" controller="Staff" action="Edit"/> 
     <mvcSiteMapNode title="View Staff" controller="Staff" action="Details"> 
      <mvcSiteMapNode > 
      ... 
     </mvcSiteMapNode> 
    </mvcSiteMapNode> 

    <mvcSiteMapNode title="Client List" controller="Client" action="List"> 
     <mvcSiteMapNode title="Create Client" controller="Client" action="Create"/> 
     <mvcSiteMapNode title="Edit Client" controller="Client" action="Edit"/> 
     <mvcSiteMapNode title="View Client" controller="Client" action="Details"> 
      <mvcSiteMapNode > 
      ... 
     </mvcSiteMapNode> 
    </mvcSiteMapNode> 
    </mvcSiteMapNode> 
</mvcSiteMap> 

그리고로 사이트 맵을 분할 할 :
루트 맵 :

<mvcSiteMapNode title="Home" controller="Home" action="Index"> 

    <subsitemap file="StaffSiteMap">// something like this. 

    <subsitemap file="ClientSiteMap">// something like this. 
    </mvcSiteMapNode> 
</mvcSiteMap> 

StaffSiteMap를 :

<mvcSiteMapNode title="Staff List" controller="Staff" action="List"> 
    <mvcSiteMapNode title="Create Staff" controller="Staff" action="Create"/> 
    <mvcSiteMapNode title="Edit Staff" controller="Staff" action="Edit"/> 
    <mvcSiteMapNode title="View Staff" controller="Staff" action="Details"> 
    <mvcSiteMapNode /> 
    ... 
    </mvcSiteMapNode> 
</mvcSiteMapNode> 

ClientSiteMap :

<mvcSiteMapNode title="Client List" controller="Client" action="List"> 
    <mvcSiteMapNode title="Create Client" controller="Client" action="Create"/> 
    <mvcSiteMapNode title="Edit Client" controller="Client" action="Edit"/> 
    <mvcSiteMapNode title="View Client" controller="Client" action="Details"> 
    <mvcSiteMapNode > 
     ... 
    </mvcSiteMapNode> 
    </mvcSiteMapNode> 
</mvcSiteMapNode> 
+0

MvcSiteMapProvider를 사용하지 않았지만 일반적으로 bultin xml 사이트 맵 공급자는 하위 사이트 맵 파일을 지원합니다. - http://msdn.microsoft.com/en-us/library/ms178426(v=vs.100).aspx –

답변

0

귀하의 접근 가능성이 당신이 필요로하는 것보다 더 많은 노드를 만드는 원인이된다. 검색 엔진에서 CRUD 작업을 색인화하는 것이 중요하지 않으면 바로 가기가 있습니다. "Index", "Create", "Edit", "Delete", "Details"에 대해 노드 집합 하나를 사용하고 preservedRouteParameters를 사용하여 가능한 모든 "id"와 일치하도록 할 수 있습니다.

먼저 노드를 올바르게 중첩시켜야 각 경우에 올바른 경로 탐색 경로가 표시됩니다.

<mvcSiteMapNode title="Staff" controller="Staff" action="List"> 
    <mvcSiteMapNode title="Create New" action="Create" /> 
    <mvcSiteMapNode title="Details" action="Details" preservedRouteParameters="id"> 
     <mvcSiteMapNode title="Edit" action="Edit" preservedRouteParameters="id"/> 
     <mvcSiteMapNode title="Delete" action="Delete" preservedRouteParameters="id"/> 
    </mvcSiteMapNode> 
</mvcSiteMapNode> 

"편집", "삭제"중 어느 것도없고, "세부 사항"노드가 메뉴 또는 다른 컨트롤에있을 것입니다, 그래서 당신은 그 경우에 그들에게 보이지 않게하기 위해 FilteredSiteMapNodeVisibilityProvider를 사용해야합니다. 기본 가시성 공급자를 구성의 FilteredSiteMapNodeVisibilityProvider로 설정할 수 있으므로 모든 노드에서 기본 가시성 공급자를 설정할 필요가 없습니다. 또한 각 노드가 부모 노드가 보이지 않을 때 보이지 않는 대신 항상 켜고 끄기 위해 VisibilityAffectsDescendants 속성을 false로 설정해야합니다.

내부 DI (Web.config의) :

<appSettings> 
    <add key="MvcSiteMapProvider_DefaultSiteMapNodeVisibiltyProvider" value="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider"/> 
    <add key="MvcSiteMapProvider_VisibilityAffectsDescendants" value="false"/> 
</appSettings> 

외부 DI (DI 모듈, StructureMap 샘플 표시) :

bool visibilityAffectsDescendants = false; 

// Module code omitted here... 

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

가시성을 마무리하려면 가시성을 설정해야 각 노드의 속성.

<mvcSiteMapNode title="Staff" controller="Staff" action="List"> 
    <mvcSiteMapNode title="Create New" action="Create" visibility="SiteMapPathHelper,!*" /> 
    <mvcSiteMapNode title="Details" action="Details" preservedRouteParameters="id" visibility="SiteMapPathHelper,!*"> 
     <mvcSiteMapNode title="Edit" action="Edit" preservedRouteParameters="id" visibility="SiteMapPathHelper,!*"/> 
     <mvcSiteMapNode title="Delete" action="Delete" preservedRouteParameters="id" visibility="SiteMapPathHelper,!*"/> 
    </mvcSiteMapNode> 
</mvcSiteMapNode> 

또한 "색인"노드의 제목을 설정하여 현재 레코드의 제목을 표시 할 수 있습니다. 각 작업 방법에서 SiteMapTitleAttribute를 사용하여이를 수행 할 수 있습니다.

[SiteMapTitle("Name")] 
public ActionResult Details(int id) 
{ 
    using (var db = new EntityContext()) 
    { 
     var model = (from staff in db.Staff 
        where staff.Id == id 
        select staff).FirstOrDefault(); 

     return View(model); 
    } 
} 

여기에는 직원 테이블에 "이름"이라는 필드가 있다고 가정합니다. 또한 편집 및 삭제 방법 (가져 오기 및 게시 모두)에서이를 설정해야합니다. 그러나 속성 대상을 ParentNode로 설정하여 "세부 정보"노드의 제목을 무시하도록해야합니다.

[SiteMapTitle("Name", Target = AttributeTarget.ParentNode)] 
public ActionResult Edit(int id) 
{ 
    using (var db = new EntityContext()) 
    { 
     var model = (from staff in db.Staff 
        where staff.Id == id 
        select staff).FirstOrDefault(); 
     return View(model); 
    } 
} 

[HttpPost] 
[SiteMapTitle("Name", Target = AttributeTarget.ParentNode)] 
public ActionResult Edit(int id, Staff staff) 
{ 
    try 
    { 
     using (var db = new EntityContext()) 
     { 
      var model = (from s in db.Staff 
         where s.Id == id 
         select s).FirstOrDefault(); 
      if (model != null) 
      { 
       model.Name = staff.Name; 

       db.SaveChanges(); 
      } 
     } 

     return RedirectToAction("Index"); 
    } 
    catch 
    { 
     return View(); 
    } 
} 

결과적으로 선택한 레코드에 따라 가짜 이동 경로가 변경됩니다.

Home > Staff 
Home > Staff > Create New 
Home > Staff > John Doe 
Home > Staff > John Doe > Edit 
Home > Staff > John Doe > Delete 

다운로드 작업 데모를 들어, How to Make MvcSiteMapProvider Remember a User's Position의 코드 다운로드에서 Forcing-A-Match 프로젝트를 참조하십시오.

MvcSiteMapProvider 버전 3.x에서이 작업을 수행 할 수도 있습니다. siteMap/providers/add 태그에 기본 가시성 공급자를 설정하고 VisibilityAffectsDescendants에 대한 부분은 무시하면됩니다.

<siteMap defaultProvider="MvcSiteMapProvider" enabled="true"> 
    <providers> 
     <clear/> 
     <add name="MvcSiteMapProvider" 
      type="MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvider" 
      siteMapFile="~/Mvc.Sitemap" 
      securityTrimmingEnabled="true" 
      cacheDuration="5" 
      enableLocalization="true" 
      scanAssembliesForSiteMapNodes="true" 
      excludeAssembliesForScan="" 
      includeAssembliesForScan="" 
      attributesToIgnore="bling,visibility" 
      nodeKeyGenerator="MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvider" 
      controllerTypeResolver="MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvider" 
      actionMethodParameterResolver="MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvider" 
      aclModule="MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvider" 
      routeMethod="" 
      siteMapNodeUrlResolver="MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvider" 
      siteMapNodeVisibilityProvider="MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider" 
      siteMapProviderEventHandler="MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider"/> 
    </providers> 
</siteMap> 

SiteMap을 더 작은 파일로 구성해야한다고 생각되면 버전 3.x에서는 불가능합니다. 외부 DI를 사용하고 동일한 SiteMap에 대해 XmlSiteMapNodeProvider를 여러 번 반복하는 경우 버전 4.x에서 구성에 여러 XML 파일을 사용할 수 있습니다. 다음은 StructureMap을 사용하여이를 수행하는 방법입니다. 각 XML 파일이 여전히 루트 노드를 필요로하지만, includeRootNode 인수가 false 인 경우는 사이트 맵에 해석되지 않습니다

// Prepare for our node providers 
var rootXmlSource = this.For<IXmlSource>().Use<FileXmlSource>() 
    .Ctor<string>("fileName").Is(HostingEnvironment.MapPath("~/Root.sitemap")); 
var staffXmlSource = this.For<IXmlSource>().Use<FileXmlSource>() 
    .Ctor<string>("fileName").Is(HostingEnvironment.MapPath("~/Staff.sitemap")); 
var clientXmlSource = this.For<IXmlSource>().Use<FileXmlSource>() 
    .Ctor<string>("fileName").Is(HostingEnvironment.MapPath("~/Client.sitemap")); 

// Register the sitemap node providers 
var siteMapNodeProvider = this.For<ISiteMapNodeProvider>().Use<CompositeSiteMapNodeProvider>() 
    .EnumerableOf<ISiteMapNodeProvider>().Contains(x => 
    { 
     x.Type<XmlSiteMapNodeProvider>() 
      .Ctor<bool>("includeRootNode").Is(true) 
      .Ctor<bool>("useNestedDynamicNodeRecursion").Is(false) 
      .Ctor<IXmlSource>().Is(rootXmlSource); 
     x.Type<XmlSiteMapNodeProvider>() 
      .Ctor<bool>("includeRootNode").Is(false) 
      .Ctor<bool>("useNestedDynamicNodeRecursion").Is(false) 
      .Ctor<IXmlSource>().Is(staffXmlSource); 
     x.Type<XmlSiteMapNodeProvider>() 
      .Ctor<bool>("includeRootNode").Is(false) 
      .Ctor<bool>("useNestedDynamicNodeRecursion").Is(false) 
      .Ctor<IXmlSource>().Is(clientXmlSource); 
     x.Type<ReflectionSiteMapNodeProvider>() 
      .Ctor<IEnumerable<string>>("includeAssemblies").Is(includeAssembliesForScan) 
      .Ctor<IEnumerable<string>>("excludeAssemblies").Is(new string[0]); 
    }); 

참고. 사실 이것은 Root.sitemap의 홈 페이지 아래 Staff.sitemap 및 Client.sitemap 파일의 노드를 중첩하는 것과 동일합니다.

Root.sitemap

<?xml version="1.0" encoding="utf-8" ?> 
<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0" 
    xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0 MvcSiteMapSchema.xsd"> 

    <mvcSiteMapNode title="Home" controller="Home" action="Index" key="Home"/> 
</mvcSiteMap> 

Staff.sitemap 루트 노드가 모든 XML 파일에 동일한 키를 가지고 확인해야

<?xml version="1.0" encoding="utf-8" ?> 
<mvcSiteMap xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0" 
    xsi:schemaLocation="http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-4.0 MvcSiteMapSchema.xsd"> 

    <mvcSiteMapNode title="Home" controller="Home" action="Index" key="Home"> 

     <mvcSiteMapNode title="Staff List" controller="Staff" action="List"> 
      <mvcSiteMapNode title="Create Staff" controller="Staff" action="Create"/> 
      <mvcSiteMapNode title="Edit Staff" controller="Staff" action="Edit"/> 
      <mvcSiteMapNode title="View Staff" controller="Staff" action="Details"> 
       <mvcSiteMapNode > 
       ... 
      </mvcSiteMapNode> 
     </mvcSiteMapNode> 

    </mvcSiteMapNode> 
</mvcSiteMap> 

주 - 가장 좋은 방법에 그것은 각 파일의 동일한 값으로 키를 명시 적으로 설정하는 것입니다. 또한 XML에서는 홈 페이지 노드보다 더 깊은 다른 파일에 노드를 부착 할 수 없습니다. 추가 파일에서 노드를 서로 중첩 할 수 있지만 모두 홈 페이지에 연결해야합니다.

그러나 IDynamicNodeProvider, ISiteMapNodeProvider 또는 [MvcSiteMapNode] attribute을 사용하면 필요에 따라 각 공급자의 노드를 중첩시킬 수 있습니다.

+0

외부 DI가 내 상황에 효과가있는 것처럼 보입니다. 하지만이 서브 사이트 맵을 함께 연결하려면 어떻게해야합니까? "Root.sitemap"은 어떻게 생겼습니까? –