MvcSiteMapProvider icon indicating copy to clipboard operation
MvcSiteMapProvider copied to clipboard

Three levels of dynamic sitemap Provider

Open mspace23 opened this issue 8 years ago • 6 comments

Hello, in my menu navigation I have three levels of choices. I mean it may be Home > History > Article but it may also be Home> Services > eServices > Article

In my class I have this code

        ` foreach (var menuItem in storeDB.SiteMenus)

            {
                DynamicNode enode = new DynamicNode();
                enode.Title = menuItem.MenuName;
              // I am not sure if the below code is correct
              //I just check if my menu is a parent menu
              //I need these so to display an extra node
                if (menuItem.MenuKind == 1)
                {

                    enode.ParentKey = "Home";

                }
                else
                {
                    enode.ParentKey = "MenuID" + menuItem.MenuID; 
                }

                enode.Key = "MenuID" + menuItem.MenuID;


                enode.Controller = "SiteContents";
                enode.Action = "ArticleDetails";
                enode.RouteValues.Add("id", menuItem.MenuID);



                enode.PreservedRouteParameters.Add("slug");

                yield return enode;
            }


            foreach (var article in storeDB.SiteContents)
            {
                DynamicNode enode = new DynamicNode();
                enode.Title = article.ArticleTitle;



                enode.ParentKey = "MenuID" + article.MenuID;




                enode.Key = "ArticleID" + article.ArticleID;

                enode.Controller = "SiteContents";
                enode.Action = "ArticleDetails";
                enode.RouteValues.Add("id", article.ArticleID);
                enode.PreservedRouteParameters.Add("slug");

                yield return enode;
            }
        }` 

in my sitemap file I have

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

   <mvcSiteMapNode title="Details" controller="SiteContents" action="ArticleDetails"     dynamicNodeProvider="MyProject.Models.ElkeDynamicNodeProvider, MyProject"/>


   </mvcSiteMapNode>

   </mvcSiteMap>`

I get the error: Additional information: Not all configured nodes could be paired with a parent node. Check your parent keys to ensure that a node with a corresponding key exists in the SiteMap. Note that the match is case sensitive.

Any Idea? thank you very much

mspace23 avatar May 04 '16 07:05 mspace23

You should look at the entire contents of the error message. It will tell you exactly which nodes are orphaned so you have an idea where to look.

Best guess is that you have orphaned records in your database which are not being filtered out in your query, which in turn is causing this issue. Most likely these orphaned records are in the SiteContents table.

NightOwl888 avatar May 05 '16 07:05 NightOwl888

Thank you for your reply. I have check the entire message and it doesn't give me the orphaned nodes. I also check my table (SiteContents) and it is ok. Every article has an id menu. When I delete the check

              `if (menuItem.MenuKind == 1)
            {

                enode.ParentKey = "Home";

            }
            else
            {
                enode.ParentKey = "MenuID" + menuItem.MenuID; 
            }`

and I give enode.ParentKey = "Home"; it works ok for the

Home >History > article

but no for the case that I have three levels like

Home> Services > eServices > Article

mspace23 avatar May 05 '16 11:05 mspace23

The entire error message, as copied from the resource file is:

<value>Not all configured nodes could be paired with a parent node. Check your parent keys to ensure that a node with a corresponding key exists in the SiteMap. Note that the match is case sensitive.

SiteMapCacheKey: '{0}'

Orphaned Nodes:

{1}</value>

If you don't at least see the header Orphaned Nodes:, then there is something in your application cutting the error message short. There is no way the raw error coming from MvcSiteMapProvider could contain less than this.

If the Orphaned Nodes section is blank this is a bug, and would appreciate your feedback.

The Orphaned Nodes section is supposed to be replaced with important details of the problem nodes including their Key, Parent Key, Controller, and Action. It is the vital information needed to resolve the issue.

NightOwl888 avatar May 05 '16 15:05 NightOwl888

Yes I see "Orphaned Nodes:" but nothing more. I supposed that the problem was with the if statement. I wil give some try and I will be back. Thank you very much

mspace23 avatar May 05 '16 16:05 mspace23

Hello I change my code in

         ` foreach (var article in storeDB.SiteContents)
            {
                DynamicNode enode = new DynamicNode();
                enode.Title = article.ArticleTitle;

                if (article.ParentMenuID == 0)
                {

                    enode.ParentKey = "Home";

                }

                else if (article.MenuID == article.ParentMenuID)
                {
                    enode.ParentKey = "ParentMenuID" + article.ParentMenuID + "MenuID" + article.MenuID;

                }
                enode.Key = "ArticleID" + article.ArticleID;
                enode.Controller = "SiteContents";
                enode.Action = "ArticleDetails";
                enode.RouteValues.Add("id", article.ArticleID);
                enode.PreservedRouteParameters.Add("slug");

                yield return enode;
            }`

and my model is

     `public class SiteContents
{
    [Key]
    [Display(Name = "ID")]
    public int ArticleID { get; set; }

    [Display(Name = "Title")]
    public String ArticleTitle { get; set; }

    [Display(Name = "Alias")]
    public String ArticleAlias { get; set; }

    [Display(Name = "Menu")]
    public int MenuID { get; set; }

    [Display(Name = "Content")]

    [AllowHtml]
    [UIHint("tinymce_full_compressed")]
    public string ArticleContent { get; set; }

    [Display(Name = "Parent Menu")]
    public int ParentMenuID { get; set; }


}`

now I dont get any error but it always displays

Home > Article

Any help? thank you

mspace23 avatar May 09 '16 07:05 mspace23

I am not sure how your database is set up, but for the SiteMap you need to specify a node for each position you want displayed in the SiteMapPath.


// "Services" node
DynamicNode level1 = new DynamicNode();
level1.Title = "Services";

level1.ParentKey = "Home";
level1.Key = "Services";
level1.Controller = "SiteContents";
level1.Action = "Services";

// Add any relevant route values...
//level1.RouteValues.Add("id", article.ArticleID);
//level1.PreservedRouteParameters.Add("slug");

yield return level1;


// "eServices" node
DynamicNode level2 = new DynamicNode();
level2.Title = "eServices";

level2.ParentKey = "Services";
level2.Key = "eServices";
level2.Controller = "SiteContents";
level2.Action = "EServices";

// Add any relevant route values...
//level2.RouteValues.Add("id", article.ArticleID);
//level2.PreservedRouteParameters.Add("slug");

yield return level2;


// Article node
DynamicNode level3 = new DynamicNode();
level3.Title = article.ArticleTitle;

level3.ParentKey = "eServices";
level3.Key =  "ArticleID" + article.ArticleID;
level3.Controller = "SiteContents";
level3.Action = "ArticleDetails";
level3.RouteValues.Add("id", article.ArticleID);
level3.PreservedRouteParameters.Add("slug");

yield return level3;

Normally, your levels would be created by a self-joining table and then you can just map the Key-Parent Key relationship exactly the same way it is done in your database.

MenuID ParentMenuID MenuTitle
1 null eServices
2 1 Services

Then you can link to the "Home" key whenever the ParentMenuID is null (and to the actual key when it is not null). Your article table would then need to reference its immediate parent menu as a foreign key.

ArticleID MenuID ArticleTitle
1 2 Some Article

NightOwl888 avatar May 11 '16 08:05 NightOwl888