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