Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breadcrumb trail for Static node inside Dynamic Node #370

Closed
abcnew opened this issue Nov 2, 2014 · 6 comments
Closed

Breadcrumb trail for Static node inside Dynamic Node #370

abcnew opened this issue Nov 2, 2014 · 6 comments

Comments

@abcnew
Copy link

abcnew commented Nov 2, 2014

Hi,

I have a static node under dynamic nodes which Iam creating through dynamic provider. However, when I click on static node, it shows only the first dynamic node in the breadcrumb.
So for ex my dynamic nodes are A,B,C,D and static node is E.
The breadcrumb on E is : A >E,even though I navigated through B, C or D.

This is my mvcsite map xml file:

 <mvcSiteMapNode title="DynamicNode" dynamicNodeProvider="CustomProvider.AreasDynamicNodeProvider,Assesmbly">
      <mvcSiteMapNode title="Details" controller="Details" action="Index" >
      </mvcSiteMapNode>
       </mvcSiteMapNode>

Help please.

thanks
abcnew

@NightOwl888
Copy link
Collaborator

I suspect that your problem is that you haven't accounted for all your route values on the details node. It would be better just to do that inside of your dynamic node provider (or another dynamic node provider).

public class AreaDynamicNodeProvider 
    : DynamicNodeProviderBase 
{ 
    public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node) 
    {
        foreach (var area in this.GetAreas()) 
        { 
            // Create a node for each area 
            DynamicNode areaNode = new DynamicNode(); 
            areaNode.Title = area; 
            areaNode.ParentKey = "Home";
            areaNode.Key = "Area_" + area;
            areaNode.Area = area;
            areaNode.Controller = "Home";
            areaNode.Action = "Index";

            yield return areaNode;

            // Create a child node for each area 
            // that is linked to the parent node
            DynamicNode detailsNode = new DynamicNode(); 
            detailsNode.Title = area + " Details"; 
            detailsNode.ParentKey = "Area_" + area;
            detailsNode.Area = area;
            detailsNode.Controller = "Home";
            detailsNode.Action = "Details";

            yield return detailsNode;
        }

    }

    private IEnumerable<string> GetAreas()
    {
        // Get your area names here
    }
}

Note also that adding multiple nodes with exactly the same route value combination is not supported. You must differentiate each node with a different URL (even if it means adding a query string value that is otherwise meaningless). See Multiple Navigation Paths to a Single Page, this article, the working demo, and the discussion of #369.

@abcnew
Copy link
Author

abcnew commented Nov 3, 2014

Hi,

Thanks for your quick repsonse. I tried changing my dynamic node provider but its still same. Here is my provider looks like:

foreach (var subjectarea in courses)
{
DynamicNode dynamicNode = new DynamicNode();
dynamicNode.Title = subjectarea.Element("Title").Value;
dynamicNode.Key = "subject" + subjectarea.Attribute("ID").Value;
dynamicNode.Controller = "CourseList";
dynamicNode.Action = "Courses";
//dynamicNode.Area = subjectarea.Attribute("ID").Value;
dynamicNode.RouteValues.Add("courseId", subjectarea.Attribute("ID").Value);
yield return dynamicNode;

            DynamicNode staticNode = new DynamicNode();
            staticNode.Title = "Course Details";
            //staticNode.Key = subjectarea.Attribute("ID").Value;
            staticNode.ParentKey = "subject" + subjectarea.Attribute("ID").Value;
            staticNode.Area = subjectarea.Attribute("ID").Value;
            staticNode.Controller = "CourseDetails";
            staticNode.Action = "Index";
            //staticNode.RouteValues.Add("coursecode", count);
            staticNode.Url = "CourseDetails?coursecode=" + count;

            yield return staticNode;
            count++;
        }

Please note if I have commented the area property on Dynamic node,otherwise it doesnt display the breadcrumb at all.

thanks
abcnew

@NightOwl888
Copy link
Collaborator

I was assuming that you are using MVC areas in your application because you didn't really give me much to go on. That is what the Area property is for. In fact, you still haven't really spelled out what is needed for me to give you a working configuration. Without knowing what your routes or URL schemes are as well as whether or not you are using MVC areas, there is no way I can help you.

That said, there is a problem with your configuration - you are configuring both a URL and route values - in this case the URL will always be used and the route values ignored. You have it right with the commented staticNode.RouteValues.Add("coursecode", count); line, but if you are not using MVC areas, then the Area line is invalid on this line as well.

Aside from the fact that each node must have a unique route configuration, each node must also account for every route value that is in the request you expect it to work with. This can be done in 2 ways - use PreservedRouteParamers to force it to match any value for a given key, or specify explicit key value pairs using the RouteValues dictionary. There is an entire article about this matching behavior and the pros and cons of each approach here.

@abcnew
Copy link
Author

abcnew commented Nov 3, 2014

Hi there,

Apologies if I havent made it clear. I shall start from the beginning.

In my MVC application, I have a view called CourseList. This view shows different courses based on the url parameter -courseId. Now each course in the list is then linked with another view called Course Details through url parameter - coursecode. Both views have seperate controllers.

Using dynamic provider above, I am able to get correct site maps. However, the course details is not working.

The route.config is only set for default:

  routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            namespaces: new[] { "Controllers" }
            ).DataTokens["UseNamespaceFallback"] = false;

thanks

@NightOwl888
Copy link
Collaborator

Ok, if I understand you correctly, then you almost had it.

    DynamicNode staticNode = new DynamicNode();
    staticNode.Title = "Course Details";
    //staticNode.Key = subjectarea.Attribute("ID").Value;
    staticNode.ParentKey = "subject" + subjectarea.Attribute("ID").Value;
    //staticNode.Area = subjectarea.Attribute("ID").Value;
    staticNode.Controller = "CourseDetails";
    staticNode.Action = "Index";
    staticNode.RouteValues.Add("coursecode", count);
    //staticNode.Url = "CourseDetails?coursecode=" + count;

Whether the coursecode is provided as a query string argument or as a route value, it will match by adding it to the route values of the node.

This will create a URL like /CourseDetails?coursecode=1 which will match an action with the signature:

public class CourseDetailsController : Controller
{
    public ActionResult Index(int coursecode)
    {
        return View();
    }
}

@abcnew
Copy link
Author

abcnew commented Nov 3, 2014

Hi,

The coursecode value is dynamic .The list in each course page is being populated with the url attached.

thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants