귀하의 접근 가능성이 당신이 필요로하는 것보다 더 많은 노드를 만드는 원인이된다. 검색 엔진에서 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을 사용하면 필요에 따라 각 공급자의 노드를 중첩시킬 수 있습니다.
MvcSiteMapProvider를 사용하지 않았지만 일반적으로 bultin xml 사이트 맵 공급자는 하위 사이트 맵 파일을 지원합니다. - http://msdn.microsoft.com/en-us/library/ms178426(v=vs.100).aspx –