title: MVC SiteMap - when different nodes point to same action SiteMap.CurrentNode does not map to the correct route
body: <h2>Setup:</h2>
  
  <p>I am using ASP.NET MVC 4, with mvcSiteMapProvider to manage my menus. </p>
  
  <p>I have a custom menu builder that evaluates whether a node is on the current branch (ie, if the <code>SiteMap.CurrentNode</code> is either the CurrentNode or the CurrentNode is nested under it).  The code is included below, but essentially checks the url of each node and compares it with the url of the currentnode, up through the currentnodes "family tree".</p>
  
  <p>The CurrentBranch is used by my custom menu builder to add a class that highlights menu items on the CurrentBranch.  </p>
  
  <h2>The Problem:</h2>
  
  <p>My custom menu works fine, but I  have found that the <code>mvcSiteMapProvider</code> does not seem to evaluate the <code>url</code> of the <code>CurrentNode</code> in a consistent manner:</p>
  
  <p><em><strong>When two nodes point to the same action and are distinguished only by a parameter of the action, SiteMap.CurrentNode does not seem to use the correct route (it ignores the distinguishing parameter and defaults to the first route that that maps to the action defined in the node).</em></strong></p>
  
  <h2>Example of the Problem:</h2>
  
  <p>In an app I have <code>Members</code>.  </p>
  
  <p>A Member has a <code>MemberStatus</code> field that can be "Unprocessed", "Active" or "Inactive".  To change the MemberStatus, I have a <code>ProcessMemberController</code> in an Area called Admin.  The processing is done using the <code>Process</code> action on the <code>ProcessMemberController</code>.</p>
  
  <p>My mvcSiteMap has two nodes that BOTH map to the <code>Process</code> action.  The only difference between them is the <code>alternate</code> parameter (such are my client's domain semantics), that in one case has a value of "Processed" and in the other "Unprocessed": </p>
  
  <p><strong>Nodes:</strong></p>
  
  <pre><code>    &lt;mvcSiteMapNode title="Process" area="Admin" controller="ProcessMembers" action="Process" alternate="Unprocessed" /&gt;
      &lt;mvcSiteMapNode title="Change Status" area="Admin" controller="ProcessMembers" action="Process" alternate="Processed" /&gt;
  </code></pre>
  
  <p><strong>Routes:</strong></p>
  
  <p>The corresponding routes to these two nodes are (again, the only thing that distinguishes them is the value of the alternate parameter):</p>
  
  <pre><code>context.MapRoute(
                      "Process_New_Members",
                      "Admin/Unprocessed/Process/{MemberId}",
                      new { controller = "ProcessMembers", 
                          action = "Process", 
                          alternate="Unprocessed", 
                          MemberId = UrlParameter.Optional }
                  );
  
  
  context.MapRoute(
                      "Change_Status_Old_Members",
                      "Admin/Members/Status/Change/{MemberId}",
                      new { controller = "ProcessMembers", 
                          action = "Process", 
                          alternate="Processed", 
                          MemberId = UrlParameter.Optional }
                  );
  </code></pre>
  
  <h2>What works:</h2>
  
  <p>The Html.ActionLink helper uses the routes and produces the urls I expect:</p>
  
  <pre><code>@Html.ActionLink("Process", MVC.Admin.ProcessMembers.Process(item.MemberId, "Unprocessed")
  
  // Output (alternate="Unprocessed" and item.MemberId = 12):   Admin/Unprocessed/Process/12
  
  
  @Html.ActionLink("Status", MVC.Admin.ProcessMembers.Process(item.MemberId, "Processed")
  
  // Output (alternate="Processed" and item.MemberId = 23):   Admin/Members/Status/Change/23
  </code></pre>
  
  <p>In both cases the output is correct and as I expect.</p>
  
  <h2>What doesn't work:</h2>
  
  <p>Let's say my request involves the second option, ie, <code>/Admin/Members/Status/Change/47</code>, corresponding to alternate = "Processed" and a MemberId of 47.</p>
  
  <p>Debugging my static CurrentBranch property (see below), I find that SiteMap.CurrentNode shows:</p>
  
  <pre><code>PreviousSibling: null
  Provider: {MvcSiteMapProvider.DefaultSiteMapProvider}
  ReadOnly: false
  ResourceKey: ""
  Roles: Count = 0
  RootNode: {Home}
  Title: "Process"
  Url: "/Admin/Unprocessed/Process/47"
  </code></pre>
  
  <p>Ie, for a request url of /Admin/Members/Status/Change/47, <code>SiteMap.CurrentNode.Url</code> evaluates to <code>/Admin/Unprocessed/Process/47</code>.  Ie, it is ignorning the <code>alternate</code> parameter and using the wrong route.</p>
  
  <h2>CurrentBranch Static Property:</h2>
  
  <pre><code>/// &lt;summary&gt;
          /// ReadOnly. Gets the Branch of the Site Map that holds the SiteMap.CurrentNode
          /// &lt;/summary&gt;
          public static List&lt;SiteMapNode&gt; CurrentBranch
          {
              get
              {
                  List&lt;SiteMapNode&gt; currentBranch = null;
                  if (currentBranch == null)
                  {
                      SiteMapNode cn = SiteMap.CurrentNode;
                      SiteMapNode n = cn;
                      List&lt;SiteMapNode&gt; ln = new List&lt;SiteMapNode&gt;();
                      if (cn != null)
                      {
                          while (n != null &amp;&amp; n.Url != SiteMap.RootNode.Url)
                          {
                              // I don't need to check for n.ParentNode == null
                              // because cn != null &amp;&amp; n != SiteMap.RootNode
                              ln.Add(n);
                              n = n.ParentNode;
                          }
                          // the while loop excludes the root node, so add it here
                          // I could add n, that should now be equal to SiteMap.RootNode, but this is clearer
                          ln.Add(SiteMap.RootNode);
  
                          // The nodes were added in reverse order, from the CurrentNode up, so reverse them.
                          ln.Reverse();
                      }
                      currentBranch = ln;
                  }
                  return currentBranch;
              }
          }
  </code></pre>
  
  <h2>The Question:</h2>
  
  <p>What am I doing wrong?  </p>
  
  <p>The routes are interpreted by Html.ActionLlink as I expect, but are not evaluated by SiteMap.CurrentNode as I expect.  In other words, in evaluating my routes, SiteMap.CurrentNode ignores the distinguishing alternate parameter.</p>