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:
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.
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:
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.