public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper) { // Try the API! Let us know if there is something we can do to make it better. // This is the same sample as the MvcMusicStore demo, and shows how you can // mark up the API semantically as a replacement for XML. // Note that the base node of this tree doesn't necessarily have to be the home page. // You can specify .WithParentKey(string) to indicate that this branch is descending from // any node defined in any other node source (XML, .NET Attributes, IDynamicNodeProivder, // ISiteMapNodeBuilder). // Be sure to try adding nodes yourself to see if you can suggest ways to make this // more intuitive, easier to read, or easier to write. return helper.RegisterNode() .MatchingRoute(x => x.WithController("Home").WithAction("Index")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,HomeTitle").WithDescription("This is the home page")) .WithSeoValues(x => x.WithSiteMaps(y => y.WithChangeFrequency(ChangeFrequency.Always).WithUpdatePriority(UpdatePriority.Normal).WithLastModifiedDate(DateTime.Parse("2002-05-30T09:00:00")))) .WithChildNodes(homeChildren => { homeChildren.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Index")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,BrowseGenresTitle")) .WithChildNodes(genreChildren => { genreChildren.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someOtherParameter", "whatever2")) .WithDisplayValues(x => x.WithTitle("Jazz 4")) .WithSeoValues(x => x.WithCanonicalKey("ABC123")); genreChildren.RegisterNode() .WithDynamicNodeProvider("MvcMusicStore.Code.StoreBrowseDynamicNodeProvider, Mvc Music Store") .WithInheritableRouteValues(x => x.WithAction("Browse").AlwaysMatchingKey("browse")) .WithInheritableDisplayValues(x => x.WithTitle("Browse")) .WithChildNodes(browseChildren => { browseChildren.RegisterNode() .WithDynamicNodeProvider("MvcMusicStore.Code.StoreBrowseDynamicNodeProvider, Mvc Music Store") .WithInheritableDisplayValues(x => x.WithTitle("Details")) .WithInheritableRouteValues(x => x.WithAction("Details")); }); genreChildren.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someParameter", "hello")) .WithDisplayValues(x => x.WithTitle("Jazz 2")) .WithSeoValues(x => x.WithCanonicalUrl("/Store/Browse/Jazz").WithMetaRobotsValues(MetaRobots.NoIndex | MetaRobots.NoFollow | MetaRobots.NoOpenDirectoryProject)) .WithKey("ABC123"); genreChildren.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someParameter", "goodbye")) .WithDisplayValues(x => x.WithTitle("Jazz 5")) .WithSeoValues(x => x.WithMetaRobotsValues(MetaRobots.NoIndex | MetaRobots.NoFollow | MetaRobots.NoOpenDirectoryProject | MetaRobots.NoYahooDirectory)); genreChildren.RegisterNode() .MatchingUrl("~//Store/Browse/Jazz?someParameter=goodbye3") // NOTE: It is not valid to apply route values to a URL based node // TODO: Add inheritable route values. .WithDisplayValues(x => x.WithTitle("Jazz 6")) .WithInheritableRouteValues(x => x.WithController("Store").WithAction("Browse").WithValues(new Dictionary<string, object> { { "id", "Jazz" }, { "someOtherParameter", "whatever" }})) .WithSeoValues(x => x.WithMetaRobotsValues(MetaRobots.NoIndex | MetaRobots.NoFollow | MetaRobots.NoOpenDirectoryProject | MetaRobots.NoYahooDirectory)); }); homeChildren.RegisterNode() .MatchingRoute(x => x.WithController("ShoppingCart").WithAction("Index")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,ReviewCartTitle")); homeChildren.RegisterNode() .AsGroupingNodeTitled("$resources:SiteMapLocalizations,CheckoutTitle") .WithKey("Checkout") .WithInheritableRouteValues(x => x.WithController("Checkout")); homeChildren.RegisterNode() .AsGroupingNodeTitled("$resources:SiteMapLocalizations,AccountTitle") .WithInheritableRouteValues(x => x.WithController("Account")) .WithChildNodes(accountChildren => { accountChildren.RegisterNode() .MatchingRoute(x => x.WithAction("LogOn")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,LogOnTitle").WithVisibilityProvider("MvcMusicStore.Code.NonAuthenticatedVisibilityProvider, Mvc Music Store")); accountChildren.RegisterNode() .MatchingRoute(x => x.WithAction("LogOff")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,LogOffTitle").WithVisibilityProvider("MvcMusicStore.Code.AuthenticatedVisibilityProvider, Mvc Music Store")); accountChildren.RegisterNode() .MatchingRoute(x => x.WithAction("Register")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,RegisterTitle").WithVisibilityProvider("MvcMusicStore.Code.NonAuthenticatedVisibilityProvider, Mvc Music Store")); accountChildren.RegisterNode() .MatchingRoute(x => x.WithAction("ChangePassword")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,ChangePasswordTitle").WithVisibilityProvider("MvcMusicStore.Code.AuthenticatedVisibilityProvider, Mvc Music Store")); accountChildren.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Browse").WithValue("id", "Jazz").WithValue("someOtherParameter", "whatever")) .WithDisplayValues(x => x.WithTitle("Jazz 3").WithVisibilityProvider("MvcMusicStore.Code.AuthenticatedVisibilityProvider, Mvc Music Store")) .WithSeoValues(x => x.WithCanonicalUrl("http://www.whatever.com/Store/Browse/Jazz")); }); homeChildren.RegisterNode() .MatchingRoute(x => x.WithArea("Admin").WithController("Home").WithAction("Index")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,AdministrationTitle").WithVisibility("SiteMapPathHelper,!*").WithVisibilityProvider("MvcSiteMapProvider.FilteredSiteMapNodeVisibilityProvider, MvcSiteMapProvider")) .WithChildNodes(adminChildren => { adminChildren.RegisterNode() .MatchingRoute(x => x.WithArea("Admin").WithController("StoreManager").WithAction("Index")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,StoreManagerTitle")) .WithChildNodes(storeManagerChildren => { storeManagerChildren.RegisterNode() .MatchingRoute(x => x.WithAction("Create")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,CreateAlbumTitle")); storeManagerChildren.RegisterNode() .MatchingRoute(x => x.WithAction("Edit")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,EditAlbumTitle")); storeManagerChildren.RegisterNode() .MatchingRoute(x => x.WithAction("Delete")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,DeleteAlbumTitle")); }); }); homeChildren.RegisterNode() .MatchingRoute(x => x.WithAction("SiteMap")) .WithDisplayValues(x => x.WithTitle("$resources:SiteMapLocalizations,SitemapTitle")) .WithUrlResolutionValues(x => x.WithUrlResolver("MvcMusicStore.Code.UpperCaseSiteMapNodeUrlResolver, Mvc Music Store")); homeChildren.RegisterNode() .MatchingUrl("http://www.microsoft.com/") .WithDisplayValues(x => x.WithTitle("Microsoft")) .WithKey("Microsoft"); }) .ToList(); }
public IEnumerable<ISiteMapNodeToParentRelation> GetSiteMapNodes(ISiteMapNodeHelper helper) { // Try the API! Let us know if there is something we can do to make it better. // This is a replacement for all of the DynamicNodeProvider implementations within // the MvcMusicStore demo, to show how this could be done. Note that in a real-world scenario // you would need to remove all of the DynamicNodeProvider declarations in the SemanticSiteMapNodeProvider // because they would be completely unnecessary. // Be sure to try adding nodes yourself to see if you can suggest ways to make this // more intuitive, easier to read, or easier to write. using (var storeDB = new MusicStoreEntities()) { // Create a node for each genre foreach (var genre in storeDB.Genres) { // This is the original dynamic node definition //DynamicNode dynamicNode = new DynamicNode("Genre_" + genre.Name, genre.Name); //dynamicNode.RouteValues.Add("genre", genre.Name); //yield return dynamicNode; // This is the fluent API version. // Note that because there is no inheritance when we do it this way, we are specifying controller and action here, too. yield return helper.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Browse").AlwaysMatchingKey("browse").WithValue("genre", genre.Name)) .WithDisplayValues(x => x.WithTitle(genre.Name)) .WithKey("Genre_" + genre.Name) .Single(); } // Create a node for each album foreach (var album in storeDB.Albums.Include("Genre")) { // This is the original dynamic node definition //DynamicNode dynamicNode = new DynamicNode(); //dynamicNode.Title = album.Title; //dynamicNode.ParentKey = "Genre_" + album.Genre.Name; //dynamicNode.RouteValues.Add("id", album.AlbumId); //if (album.Title.Contains("Hit") || album.Title.Contains("Best")) //{ // dynamicNode.Attributes.Add("bling", "<span style=\"color: Red;\">hot!</span>"); //} //yield return dynamicNode; // This is the fluent API version. // Note that because there is no inheritance when we do it this way, we are specifying controller and action here, too. var customAttributes = new Dictionary<string, object>(); if (album.Title.Contains("Hit") || album.Title.Contains("Best")) { customAttributes.Add("bling", "<span style=\"color: Red;\">hot!</span>"); } yield return helper.RegisterNode() .MatchingRoute(x => x.WithController("Store").WithAction("Details").WithValue("id", album.AlbumId)) .WithDisplayValues(x => x.WithTitle(album.Title)) .WithParentKey("Genre_" + album.Genre.Name) .WithCustomAttributes(customAttributes) .Single(); } } }