Click to Rate and Give Feedback
MSDN
MSDN Library
Visual Studio 2008
Visual Studio
 How to: Programmatically Modify Sit...

  Switch on low bandwidth view
This page is specific to
Microsoft Visual Studio 2008/.NET Framework 3.5

Other versions are also available for the following:
ASP.NET
How to: Programmatically Modify Site-Map Nodes in Memory

Web sites frequently use dynamic URLs containing information that is appended as query strings. For example, the site for a newsgroup or forum might include static URLs that refer to forums or groups as well as dynamic URLs for each post. A URL for a post might be in the following format: http://www.microsoft.com/newsgroups/ShowPost.aspx?ForumID=2&PostID=53

Updating a site map to list the URL for every post is not an efficient approach because nodes cannot be added to a site map programmatically. However, when a user is viewing a post, you can use the SiteMapPath control to display the navigation path back to the root node and dynamically append query strings to each link in the path, identifying the post, forum, or group. For example, your navigation path to the preceding post might look like the following:

Home > Forum List > Post List

The static Url property of the site-map node for Posts might be set to http://www.microsoft.com/newsgroups/ShowPost.aspx. But in memory, you can modify the URL in the SiteMapPath control to identify the forum and the specific post.

You can change site-map nodes in memory by using the SiteMapResolve event as shown in the following procedure and example.

To programmatically change site-map nodes

  1. In the code for a Web forms page, create a method to handle the SiteMapResolve event. For example, the following declaration creates a method called ExpandForumPaths.

    C#
    private SiteMapNode ExpandForumPaths(Object sender, 
                                         SiteMapResolveEventArgs e)
    

    Visual Basic
    Private Function ExpandForumPaths(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
    
  2. In your event handler, obtain a reference to the current node and clone it. For example, if the node is a newsgroup posting, your code might look like the following.

    C#
    SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
    SiteMapNode tempNode = currentNode;
    

    Visual Basic
    Dim currentNode As SiteMapNode = SiteMap.CurrentNode.Clone(True)
    Dim tempNode As SiteMapNode = currentNode
    

    The tempNode variable returns a site-map node in memory that can be traversed, modifying each Url property or other properties. The reference in nodeCopy is maintained separately because the expected return value from the event handler is a reference to the current node. However, the tempNode variable will be used to recursively move up the navigation structure.

    NoteNote:

    Because the cloned node is separate from the static site-navigation structure, the changes to the Url properties do not persist in memory nor are they save to disk.

  3. Change the Url properties of the current node and its parent node to include query-string information that lists the post, forum, and group identifiers.

    For example, the following code example assumes the existence of three methods that obtain the identifiers.

    C#
    int forumGroupID = GetMostRecentForumGroupID();
    int forumID = GetMostRecentForumID(forumGroupID);
    int postID = GetMostRecentPostID(forumID);
    
    if (0 != postID)
    {
        tempNode.Url = tempNode.Url + "?PostID=" + postID.ToString();
    }
    
    if ((null != (tempNode = tempNode.ParentNode)) &&
        (0 != forumID))
    {
        tempNode.Url = tempNode.Url + "?ForumID=" + forumID.ToString();
    }
    
    if ((null != (tempNode = tempNode.ParentNode)) &&
        (0 != forumGroupID))
    {
        tempNode.Url = tempNode.Url + "?ForumGroupID=" + forumGroupID.ToString();
    }
    

    Visual Basic
    Dim forumGroupID As Integer = GetMostRecentForumGroupID()
    Dim forumID As Integer = GetMostRecentForumID(forumGroupID)
    Dim postID As Integer = GetMostRecentPostID(forumID)
    
    If Not (0 = postID) Then
        tempNode.Url = tempNode.Url & "?PostID=" & postID.ToString()
    End If
    
    tempNode = tempNode.ParentNode
    If Not (0 = forumID) And Not (Nothing = tempNode) Then
        tempNode.Url = tempNode.Url & "?ForumID=" & forumID.ToString()
    End If
    
    tempNode = tempNode.ParentNode
    If Not (0 = ForumGroupID) And Not (Nothing = tempNode) Then
        tempNode.Url = tempNode.Url & "?ForumGroupID=" & forumGroupID.ToString()
    End If
    
    NoteNote:

    The if statements are used to ensure that query strings are only added to existing site-map nodes, and only if the group, form, and post identifiers are available.

  4. Return the cloned node by using the following line of code.

    C#
    return currentNode;
    

    Visual Basic
    Return currentNode
    
  5. Register your event handler in the Page_Load method. For example, your code might look like the following example.

    C#
    SiteMap.SiteMapResolve +=
      new SiteMapResolveEventHandler(this.ExpandForumPaths);
    

    Visual Basic
    AddHandler SiteMap.SiteMapResolve, AddressOf Me.ExpandForumPaths
    
    NoteNote:

    The SiteMapResolve event is raised when the site-map provider accesses the CurrentNode property, such as when the SiteMapPath control is rendering a navigation structure.

  6. Add a SiteMapPath control in your Web Forms page to view the navigation structure. Your SiteMapPath control might look like the following.

    <asp:SiteMapPath
    id="SiteMapPath1"
    runat="server"
    RenderCurrentNodeAsLink="true" />
    
  7. Make sure that there is a node for your Web Forms page in your site-map file. For example, if your Web Forms page is called ShowPost.aspx, your Web.sitemap file might look like the following.

    <?xml version="1.0" encoding="utf-8" ?>
    <siteMap>
      <siteMapNode
        title="Forum Group" 
        description="Forum Group List"
        url="default.aspx">
        <siteMapNode 
          title="Forum" 
          description="Forum List"
          url="ShowForum.aspx">
          <siteMapNode 
            title="Post" 
            description="Post List" 
            url="ShowPost.aspx" />
        </siteMapNode>
      </siteMapNode>
    </siteMap>
    

The following code example demonstrates how you can handle the SiteMapResolve event on an ASP.NET Web page to modify the target URLs that are displayed by the SiteMapPath control. In this example, the current page is a post page in an online bulletin board or forum. To render more meaningful site navigation, the URLs of the nodes that are displayed by the SiteMapPath control are appended with context-relevant query strings. Use the following code to render the control.

Visual Basic
<asp:SiteMapPath
id="SiteMapPath1"
runat="server"
RenderCurrentNodeAsLink="true" />

C#
<asp:SiteMapPath
id="SiteMapPath1"
runat="server"
RenderCurrentNodeAsLink="true" />

When running the example, place your cursor over the links in the SiteMapPath control to see how the URLs are changed.

This example does not add SiteMapNode items in the Web.sitemap file; the Web.sitemap file can only be edited manually.

NoteNote:

It is safe to access the CurrentNode property from within the SiteMapResolveEventHandler. The ASP.NET site-navigation infrastructure guards against infinite recursion in this case.

This example assumes that you already have a valid site-map file, and that the current page is at least three nodes deep in the site-map structure. For more information about creating site maps, see ASP.NET Site Maps.

Visual Basic
Private Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)

    ' The ExpandForumPaths method is called to handle
    ' the SiteMapResolve event.
    AddHandler SiteMap.SiteMapResolve, AddressOf Me.ExpandForumPaths

End Sub

Private Function ExpandForumPaths(ByVal sender As Object, ByVal e As SiteMapResolveEventArgs) As SiteMapNode
    ' The current node represents a Post page in a bulletin board forum.
    ' Clone the current node and all of its relevant parents. This
    ' returns a site map node that a developer can then
    ' walk, modifying each node.Url property in turn.
    ' Since the cloned nodes are separate from the underlying
    ' site navigation structure, the fixups that are made do not
    ' effect the overall site navigation structure.
    Dim currentNode As SiteMapNode = SiteMap.CurrentNode.Clone(True)
    Dim tempNode As SiteMapNode = currentNode

    ' Obtain the recent IDs.
    Dim forumGroupID As Integer = GetMostRecentForumGroupID()
    Dim forumID As Integer = GetMostRecentForumID(forumGroupID)
    Dim postID As Integer = GetMostRecentPostID(forumID)

    ' The current node, and its parents, can be modified to include
    ' dynamic querystring information relevant to the currently
    ' executing request.
    If Not (0 = postID) Then
        tempNode.Url = tempNode.Url & "?PostID=" & postID.ToString()
    End If

    tempNode = tempNode.ParentNode
    If Not (0 = forumID) And Not (tempNode Is Nothing) Then
        tempNode.Url = tempNode.Url & "?ForumID=" & forumID.ToString()
    End If

    tempNode = tempNode.ParentNode
    If Not (0 = ForumGroupID) And Not (tempNode Is Nothing) Then
        tempNode.Url = tempNode.Url & "?ForumGroupID=" & forumGroupID.ToString()
    End If

    Return currentNode

End Function



...


' These methods are just placeholders for the example.
' One option is to use the HttpContext or e.Content object
' to obtain the ID.
Private Function GetMostRecentForumGroupID() As Integer
    Return 24
End Function

Private Function GetMostRecentForumID(ByVal forumGroupId As Integer) As Integer
    Return 128
End Function

Private Function GetMostRecentPostID(ByVal forumId As Integer) As Integer
    Return 317424
End Function

C#
private void Page_Load(object sender, EventArgs e)
{
    // The ExpandForumPaths method is called to handle
    // the SiteMapResolve event.
    SiteMap.SiteMapResolve +=
      new SiteMapResolveEventHandler(this.ExpandForumPaths);
}

private SiteMapNode ExpandForumPaths(Object sender, SiteMapResolveEventArgs e)
{
    // The current node represents a Post page in a bulletin board forum.
    // Clone the current node and all of its relevant parents. This
    // returns a site map node that a developer can then
    // walk, modifying each node.Url property in turn.
    // Since the cloned nodes are separate from the underlying
    // site navigation structure, the fixups that are made do not
    // effect the overall site navigation structure.
    SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
    SiteMapNode tempNode = currentNode;

    // Obtain the recent IDs.
    int forumGroupID = GetMostRecentForumGroupID();
    int forumID = GetMostRecentForumID(forumGroupID);
    int postID = GetMostRecentPostID(forumID);

    // The current node, and its parents, can be modified to include
    // dynamic querystring information relevant to the currently
    // executing request.
    if (0 != postID)
    {
        tempNode.Url = tempNode.Url + "?PostID=" + postID.ToString();
    }

    if ((null != (tempNode = tempNode.ParentNode)) &&
        (0 != forumID))
    {
        tempNode.Url = tempNode.Url + "?ForumID=" + forumID.ToString();
    }

    if ((null != (tempNode = tempNode.ParentNode)) &&
        (0 != forumGroupID))
    {
        tempNode.Url = tempNode.Url + "?ForumGroupID=" + forumGroupID.ToString();
    }

    return currentNode;
}


...


// These methods are just placeholders for the example.
// One option is to use the HttpContext or e.Content object
// to obtain the ID.
private int GetMostRecentForumGroupID()
{
    return 24;
}

private int GetMostRecentForumID(int forumGroupId)
{
    return 128;
}

private int GetMostRecentPostID(int forumId)
{
    return 317424;
}

An important aspect of working with query strings and form data is validating the data that is passed. ASP.NET provides a set of validation controls that provide an easy-to-use but powerful way to check for errors and, if necessary, display messages to the user. Validation controls were not used in the preceding example in order to focus on the task of changing site-map nodes. For information about how to add validation to your code, see Validation ASP.NET Controls.

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Typos or unclear documentation      EdSF   |   Edit   |   Show History
#2: "... The reference in nodeCopy is maintained..." - where/what is "nodeCopy"?

Feedback: there must be a much simpler way to explain all this

Tags What's this?: Add a tag
Flag as ContentBug
This should be an Application level event      DaveSussman   |   Edit   |   Show History
Tags What's this?: Add a tag
Flag as ContentBug
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Page view tracker