Web design and hosting, database, cloud and social media solutions that deliver business results
  • Business Solutions
    • Robotic Process Automation
    • Bespoke Software
    • Database Services
      • Data Integration
      • Datawarehouse Services
      • Power BI
      • Server Upgrade and DBA Services
    • Web Services
      • Logo Design
      • Payment Gateways
      • Web Localisation and Translation
      • Web Site Optimisation
      • Web Site Security
      • Technical Tools
    • Cloud Services
      • Amazon Web Services
      • Google Cloud Services
      • Microsoft Azure
    • Microsoft 365
      • Enabling the Multi Factor Authentication Application
      • Office 365 DNS Settings Generator
    • IT Hardware
    • Social Media Services
  • Academy
    • Our Test Environment
    • Learning Databases
      • The Basics
      • Get Open Query
      • SQL Server Data
      • SQL Server Maintenance
      • Using SQL Server Dates
      • Using SQL Server Functions
      • Using SQL Server Pivot-Unpivot
      • Technical Tools
    • Learning Web Design
      • Building Ousia Content Management System
      • Using ASP-NET
      • Using CSS
      • Using JavaScript
    • Learning Cloud and IT Services
      • Task Scheduler Error 2147943645
      • Blocking Blank Senders
      • Requesting SSL and Generation of PFX file in OpenSSL Simple Steps
    • Using Social Media
      • Asking for a Google Review
      • Changing a Facebook account from personal to business
      • Choosing where to focus Social Media effort
      • Social Media Image Sizes
      • Using Meta Data to set Social Media Images
  • About
    • Blog
      • Building an entry level gaming machine
      • Google Core Update Jan 2020
      • Hot Chilli Internet Closure
      • How To Choose Content For Your Website Adverts Leaflets
      • Preventing Online Scam
      • Skimmers of the gig economy
      • The most annoying things about websites on the Internet
      • Top 5 websites for free Vector Graphics
    • Careers
      • Translator English-Japanese
      • Translator English-Portuguese
      • Translator English-Spanish
      • Translator English-Turkish
    • Portfolio
    • Regulatory
    • Team
      • Chester Copperpot
      • Gavin Clayton
      • Sai Gangu
      • Suneel Kumar
      • Surya Mukkamala
English (EN-GB)English (EN-US)हिंदी (HI)italiano (IT)日本語 (JA)Português (PT)

Replacing Session State

A look at replacing Session State in an ASP.NET application

About

I have spent the last few years tinkering with custom Content Management Systems, culminating in the latest version of Ousia. 

Previous versions had always used ASP.NET Session State to maintain items between postbacks, or to hold information while a request was happening, in combination with a custom request handler that populates various page route data items.

Session state is a handy way of storing the data, but I had found a few drawbacks on the out of the box functionality;

  • If a user was editing a lengthy document, the session could run out before they saved the item
  • Restricted to a single IIS process running the entire application.

I had been looking at getting Ousia migrated from a standard worker process to a Web Garden, and knew that I would have to find some alternative way of remembering data cross process. Some of the solutions I had previously used or encountered online included and had various pros and cons;

Options

  • HttpContext
  • ViewState
  • Cookies
  • SessionState in SQL Server

Logic dictated (my logic anyway) to me that I had to split the purpose of the data in two. 

Was it cross-page/cross-request data, or something that I needed to remember for just the time the request took to process?

Request Processing Values – Easy Win

I very quickly realised that there is no need to use SessionState to remember data for the time a request took to process. This was easily handled by HttpContext.

I may use this in complex postback scenarios to set a screen visibility further down the request chain, something along these lines. To make this switch, which I would recommend, then you are looking at something similar to the code below.

VB.NET

Session("YourVariable") = "Test"
Dim TestSession As String = Session("YourVariable").ToString
HttpContext.Current.Items("YourVariable") = "Test"
Dim TestContext As String = HttpContext.Current.Items("YourVariable").ToString

It was that simple, literally just change the code from Session to Context and half the problems had gone away.

It didn't solve the process of remembering data between postbacks though, that would take more thought.


Cross Request Data

I decided to use cookies to remember the data cross request, but thought I would take it to the next level in terms of storing and accessing the data, by creating a series of functions and subs that would make it easier elsewhere to access this data, cross sub domain.

Domain Function

By default, a cookie created in IIS would be at the full domain level and accessible only to that domain. This wouldn't help with the different subdomains I have on both the Claytabase and gsclayton.net sites. Luckily you can set the cookie domain.

I found that during the writing of the other parts I was re-using this domain functionality, so moved it to a separate function. This was required for setting cookies on internal servers.

VB.NET

Public Shared Function UpdDomain(Domain As String) As String
    Dim DomainStr As String = ""
    If Domain.IndexOf(".") > -1 Then
        DomainStr = Domain
    Else
        DomainStr = ""
    End If
    Return DomainStr
End Function

Cookie Expiration

Yep, cookies don't come back with an expiry date you sent them out with.

Top Tip – Save the expiration as ticks within the cookie.

VB.NET

Public Shared Function GetExpires(Cookie As HttpCookie) As Long
    Dim Expires As Long = 0
    If Not IsNothing(Cookie("Expires")) Then
        Try
            Expires = Cookie("Expires").ToString
        Catch
        End Try
    End If
    Return Expires
End Function

Setting Cookie Values

Now two subs are needed to create and set the cookie values. These require both the Request and Response as parameters, a cookie name, domain and timeout in minutes to work. 

The setting of the values happens in the second of the subs, and you just pass in the additional Field and Value as strings.

VB.NET

Public Shared Sub PersistenceCreate(Request As HttpRequest, Response As HttpResponse, CookieName As String, Domain As String, TimeOut As Integer)
    If IsNothing(Request.Cookies(CookieName)) Then
        Dim PersistenceCookie As New HttpCookie(CookieName)
        Domain = UpdDomain(Domain)
        PersistenceCookie.Domain = Domain
        PersistenceCookie.Expires = DateAdd(DateInterval.Minute, TimeOut, Now.ToUniversalTime())
        PersistenceCookie("Expires") = PersistenceCookie.Expires.Ticks
        Response.Cookies.Add(PersistenceCookie)
    End If
End Sub
Public Shared Sub PersistenceSet(Request As HttpRequest, Response As HttpResponse, CookieName As String, Domain As String, TimeOut As Integer,
                                 Field As String, Value As String)
    If IsNothing(Request.Cookies(CookieName)) Then
        PersistenceCreate(Request, Response, CookieName, Domain, TimeOut)
    End If
    Dim PersistenceCookie As HttpCookie = Request.Cookies(CookieName)
    Dim Expires As Long = GetExpires(PersistenceCookie)
    Domain = UpdDomain(Domain)
    PersistenceCookie.Domain = Domain
    If Expires < DateAdd(DateInterval.Minute, TimeOut, Now.ToUniversalTime()).Ticks Then
        PersistenceCookie.Expires = DateAdd(DateInterval.Minute, TimeOut, Now.ToUniversalTime())
        PersistenceCookie("Expires") = PersistenceCookie.Expires.Ticks
    Else
        PersistenceCookie.Expires = New DateTime(Expires)
        PersistenceCookie("Expires") = PersistenceCookie.Expires.Ticks
    End If
    PersistenceCookie.Item(Field) = Value
    Response.Cookies.Add(PersistenceCookie)
End Sub

Getting Cookie Values

These are two slightly different flavours of the same thing. The first returns a value from the cookie if it exists or an empty string, the second a simple Boolean if the cookie value is equal to the input variable.

VB.NET

Public Shared Function PersistenceGet(Request As HttpRequest, CookieName As String, Field As String) As String
    Dim r As String = ""
    If Not IsNothing(Request.Cookies(CookieName)) Then
        If Not IsNothing(Request.Cookies(CookieName)(Field)) Then
            r = Request.Cookies(CookieName)(Field).ToString
        End If
    End If
    Return r
End Function
Public Shared Function PersistenceCheck(Request As HttpRequest, CookieName As String, Field As String, Value As String) As Boolean
    Dim r As Boolean = False
    If Not IsNothing(Request.Cookies(CookieName)) Then
        If Not IsNothing(Request.Cookies(CookieName)(Field)) Then
            If Request.Cookies(CookieName)(Field) = Value Then
                r = True
            End If
        End If
    End If
    Return r
End Function

Cookie Recycling

Hold on a second! Don't run off with the previous bits just yet. This is where the magic happens.

You will quickly realise that the cookie will just expire unless you keep resetting a value every so often. This is plugged into our request handler to remember our persistence cookie among other things. It simply resets the cookie expiry if it falls below 20 minutes.

Public Shared Sub PersistenceRecycle(Request As HttpRequest, Response As HttpResponse, CookieName As String, Domain As String)
    If Not IsNothing(HttpContext.Current.Request.Cookies(CookieName)) Then
        Dim PersistenceCookie As HttpCookie = HttpContext.Current.Request.Cookies(CookieName)
        Dim Expires As Long = GetExpires(PersistenceCookie)
        Domain = UpdDomain(Domain)
        If Expires < DateAdd(DateInterval.Minute, 20, Now.ToUniversalTime()).Ticks Then
            PersistenceCookie.Expires = DateAdd(DateInterval.Minute, 20, Now.ToUniversalTime())
            PersistenceCookie("Expires") = PersistenceCookie.Expires.Ticks
            PersistenceCookie.Domain = Domain
            Response.Cookies.Add(PersistenceCookie)
        End If
    End If
End Sub

Recap and Usage

Using the functions couldn't be simpler. A simple example may be to set a dropdown field selected value for the next time the user came back. In this scenario we would use it as follows.

To test, lets add a create a new web form with a simple dropdown, set to auto postback on change.

HMTL

<asp:dropdownlist runat="server" id="CookieDrop" AutoPostBack="true">
    <asp:ListItem Value="1">Value 1</asp:ListItem>
    <asp:ListItem Value="2">Value 2</asp:ListItem>
    <asp:ListItem Value="3">Value 3</asp:ListItem>
    <asp:ListItem Value="4">Value 4</asp:ListItem>
</asp:dropdownlist>

VB.NET

Imports CookieModule 'or whatever you called it
Public Class DropDownCookie
    Inherits System.Web.UI.Page
    Protected Sub CookieDrop_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CookieDrop.SelectedIndexChanged
        'Set the cookie for one minute...
        PersistenceSet(Request, Response, "DropDownTest", "", 1, "SelectedValue", CookieDrop.SelectedValue)
    End Sub
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        GetData()
        PersistenceRecycle(Request, Response, "DropDownTest", "")
        If Not IsPostBack Then 'Delete if you want to remove ViewState!
            SetDropDownVal()
        End If
    End Sub
    Protected Sub Page_PreRender() Handles Me.PreRender
    End Sub
    Protected Sub GetData()
        'Bind Data to DropDown
    End Sub
    Protected Sub SetDropDownVal()
        Dim DropDownVal As Integer
        If PersistenceGet(Request, "DropDownTest", "SelectedValue") <> "" Then
            If IsNumeric(PersistenceGet(Request, "DropDownTest", "SelectedValue")) Then
                DropDownVal = PersistenceGet(Request, "DropDownTest", "SelectedValue")
                Try
                    CookieDrop.SelectedValue = DropDownVal
                Catch
                End Try
            End If
        End If
    End Sub
End Class

Author

Was this helpful?

Please note, this commenting system is still in final testing.

Website design by Claytabase

This is a section of code that has been modified from Ousia Content Management System code, one of the quickest and most optimised systems on the market, part of our website design services.

These are available with sites starting at around £500.

more: Responsive and fast. Web Development, Design and Hosting with Content Management System
Copyright Claytabase Ltd 2020

Registered in England and Wales 08985867

Site Links

RSSLoginLink Cookie PolicySitemap

Social Media

facebook.com/Claytabaseinstagram.com/claytabase/twitter.com/Claytabaselinkedin.com/company/claytabase-ltd

Get in Touch

+442392064871info@claytabase.co.ukClaytabase Ltd, Unit 3d, Rink Road Industrial Estate, PO33 2LT, United Kingdom

Partnered With

The settings on this site are set to allow all cookies. These can be changed on our Cookie Policy & Settings page.
By continuing to use this site you agree to the use of cookies.
Ousia Logo
Logout
Ousia CMS Loader