Search code examples
asp.net-mvc-3asp.net-mvc-5mvcsitemapprovider

Working with child nodes of dynamicNodeProvider


I use this project to generate the sitemap path.

In my application I would like the sitemap path to stay as follows:

Path: Home > Projects > {project-name}
Url: /projects/{url-project}

Path: Home > Projects > {project-name} > Photos
Url: /projects/{url-project}/photos

Path: Home > Projects > {project-name} > Addresses
Url: /projects/{url-project}/addresses

Path: Home > Projects > {project-name} > Admin
Url: /projects/{url-project}/admin

Attemps

For this I created an implementation of DynamicNodeProviderBase

public class ProjectDetailsDynamicNodeProvider : DynamicNodeProviderBase
{
    private readonly IProjectRepository _projectRepository;
    public ProjectDetailsDynamicNodeProvider()
    {
        _projectRepository = DependencyResolver.Current.GetService<IProjectRepository>();
    }

    #region Overrides of DynamicNodeProviderBase

    public override IEnumerable<DynamicNode> GetDynamicNodeCollection()
    {
        // Build value 
        var returnValue = new List<DynamicNode>();
        var listDB = (from p in _projectRepository.Query()
                      select new { p.Name, p.Keyword, p.Description });

        // Create a node for each project
        foreach (var project in listDB.ToList())
        {
            var node = new DynamicNode { Title = project.Name, Description = project.Description };
            node.RouteValues.Add("url", project.Keyword);

            returnValue.Add(node);
        }

        // Return 
        return returnValue;
    }

    #endregion
}

Mvc.sitemap

<mvcSiteMapNode title="Projects" controller="Project" action="Index">
  <mvcSiteMapNode title="New project" controller="Project" action="Create" />

  <mvcSiteMapNode title="Project" action="About" controller="Project" dynamicNodeProvider="BindSolution.Infra.ProjectDetailsDynamicNodeProvider, BindSolution">
    <mvcSiteMapNode title="Photos" controller="Project" action="Photos" />
    <mvcSiteMapNode title="Addresses" controller="Project" action="Addresses" />
    <mvcSiteMapNode title="Admin" controller="Project" action="Admin" />
  </mvcSiteMapNode> 
</mvcSiteMapNode>

Result

Path: Home > Projects > {project-name}
Url: /projects/{url-project}

Path: Project > Photos
Url: /projects/{url-project}/photos

Path: Project > Addresses
Url: /projects/{url-project}/addresses

Path: Project > Admin
Url: /projects/{url-project}/admin

Research

Looking on the internet, I found this question on stackoverflow, but not quite understand the resolution or it does not fit into my question. Anyway, if this is the answer you could give me more details of how to implement the solution?

Thank you all for your help!


Solution

  • Our code is /country/{countryname}/ /country/{countryname}/profiles

    And this is what I came up. So I would substitute country with url-project. The only problem that I am noticing with this method, so I don't know if it's the best, is that with our countries (we have 210) we run out of memory. I did this was states (50) and a few others and did not have a problem. I'm having a problem with countries though, also we have 9 different pages listed at the top. When I keep it to 4, I don't have a problem. Hope this helps.

    public class CountriesDynamicNodeProvider : DynamicNodeProviderBase
    {
        globalEDGEDataContext _db = new globalEDGEDataContext();
        public override IEnumerable<DynamicNode> GetDynamicNodeCollection()
        {
            var returnValue = new List<DynamicNode>();
            foreach (var category in _db.CountriesList().Select(a => a.Title))
            {
                DynamicNode node = new DynamicNode("country_" + Tags.MakeUrlFriendly(category), category);
                node.RouteValues.Add("country", Tags.MakeUrlFriendly(category));
                yield return node;
            }
        }
    }
    
    public class CountriesPagesDynamicNodeProvider : DynamicNodeProviderBase
    {
        globalEDGEDataContext _db = new globalEDGEDataContext();
        public override IEnumerable<DynamicNode> GetDynamicNodeCollection()
        {
            foreach (var category in _db.CountriesList().Select(a=>a.Title))
            {
                DynamicNode node = new DynamicNode();
                node.Title = "Profile";
                node.ParentKey = "country_" + Tags.MakeUrlFriendly(category);
                node.RouteValues.Add("country", Tags.MakeUrlFriendly(category));
                yield return node;
            }
        }
    }
    

    The example works for MVC5 as well. Slightly modified:

      public class DepartmentEmployeeDynamicNodeProvider: DynamicNodeProviderBase
    {
        AlertsContext db = new AlertsContext();
    
        public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
        {
            // Build value 
            var returnValue = new List<DynamicNode>();
    
            // Create a node for each department 
            foreach (var department in db.Departments)
            {
                var dynNode = new DynamicNode();
                dynNode.Title = department.DepartmentName;
                dynNode.RouteValues.Add("id", department.ID);
    
                returnValue.Add(dynNode);
            }
    
            // Return 
            return returnValue; 
        }
    }