Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Avoid session loss when using Cookieless sessions with XML Sitemap Provider

3.86/5 (5 votes)
28 Oct 2008CPOL2 min read 1   113  
This article will explain how to avoid session loss when you use Cookiless sessions with the XML Sitemap Provider.

Introduction

In this article, I will show you how you can avoid session loss when using Site maps in your website that is configured to use cookieless sessions.

Background

By default, ASP.NET uses cookies to remember the user sessions between requests. However,when using cookieless sessions ,the session ID will not be stored in the cookie; instead, the runtime will insert the Session ID in the page URL so that it can extract that ID when the user submits the page. See the image below of how the ID will look like:

CookieLessDemo

The problem will occur when you use SiteMap files in a website that is configured to use cookie-less sessions. In that case, the SiteMap provider will not insert the session ID in the returned nodes that were populated from the SiteMap file, and so any navigation control (e.g., TreeView, Menu) that uses the SiteMap provider will have items that don't contain the session ID, and so, when the user navigates your website using those controls, the user session will be lost on every navigation.

Using the code

There are many solutions for the above mentioned problem. One simple solution is to handle the databound events for the navigation control and fix the URLs that are generated in the control.

For example, if you are using a TreeView control, you can handle its NodeDataBound event.

C#
protected void TreeView1_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
    e.Node.NavigateUrl = 
      HttpContext.Current.Response.ApplyAppPathModifier(e.Node.NavigateUrl);
}

Note that the ApplyAppPathModifier method will automatically insert the session ID to the URL.

For more information on how to apply the mentioned solution, see my blog post here.

Handling the control databound events will be a simple solution, but it could not be a practical one especially when you are working with many SiteMap files and many navigation controls. In that case, you will need to handle every control event.

The other solution is to inherit from the XmlSiteMapprovider class and override some properties and functions; see the custom provider code below:

VB
Imports System.Web

Public Class SiteMapProviderForCookieeLessSessions
    Inherits XmlSiteMapProvider

    Public Overrides ReadOnly Property CurrentNode() As System.Web.SiteMapNode
        Get
            Dim cn As SiteMapNode = MyBase.CurrentNode.Clone()
            ProcessUrl(cn)
            Return cn
        End Get
    End Property

    Public Overrides ReadOnly Property RootNode() As System.Web.SiteMapNode
        Get
            Dim Root As SiteMapNode = MyBase.RootNode.Clone()
            ProcessUrl(Root)
            Return Root
        End Get
    End Property

    Public Overrides Function GetParentNode(ByVal node As _
           System.Web.SiteMapNode) As System.Web.SiteMapNode
        Dim ParentNode As SiteMapNode = MyBase.GetParentNode(node).Clone()
        ProcessUrl(ParentNode)
        Return ParentNode
    End Function

    Public Overrides Function GetChildNodes(ByVal node As _
           System.Web.SiteMapNode) As System.Web.SiteMapNodeCollection
        Dim CurrentChilds As SiteMapNodeCollection = MyBase.GetChildNodes(node)
        Dim ModifiedChilds As New SiteMapNodeCollection()
        For Each tnode As SiteMapNode In CurrentChilds
            Dim cnode As SiteMapNode = tnode.Clone()
            ProcessUrl(cnode)
            ModifiedChilds.Add(cnode)
        Next
        Return ModifiedChilds
    End Function

    Private Sub ProcessUrl(ByVal node As SiteMapNode)
        If node.Url.Length > 0 Then
            If Not HttpContext.Current Is Nothing AndAlso _
                   Not HttpContext.Current.Response Is Nothing Then
                node.Url = HttpContext.Current.Response.ApplyAppPathModifier(node.Url)
            End If
        End If
    End Sub

End Class

In the mentioned code, there is a private function ProcessUrl which is used to fix the URLs of the returned nodes. For more information about the overriden properties and methods, see the MSDN documentation for the XMLSiteMapprovider members.

I attached the CustomProvider code as a separate class project. Also, I created a demo website which contains two menu controls, one that uses the default provider which doesn't append the session ID in the generated nodes, and another menu that uses the custom provider which handles this issue perfectly. The website that I included is configured to use cookie-less sessions from the web.config file, and also, I registered the custom provider in the web.config file under the SiteMap section.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)