I had a need to access the session state on the end of every request, even those on Response.Redirect. It sounds simple, and it is. It just took a while to find out what method is always called on every page before the data (headers and content) is sent back to the client. Even on Response.Redirect's.In the global.asax file, it is the method Application_PostRequestHandlerExecute. It is the last method that is called that has access to the session state. Here's a basic example:

using System;
using System.Web; 
using System.Web.Security; 
using System.Web.SessionState; 
 
namespace TestWebApp 
{ 
    public class Global : System.Web.HttpApplication 
    { 
    
        void Application_Start(object sender, EventArgs e) 
        { 
        }  
        
        void Application_End(object sender, EventArgs e) 
        { 
        } 
        
        void Application_Error(object sender, EventArgs e) 
        { 
        } 
        
        void Session_Start(object sender, EventArgs e) 
        { 
        } 
        
        void Session_End(object sender, EventArgs e) 
        { 
        } 
        
        void Application_PostRequestHandlerExecute(object sender, EventArgs e) 
        { 
            DataProvider.SaveSession(); 
            Response.Cookies["lastaccessed"].Value = DateTime.Now.Ticks.ToString(); 
        } 
        
        void Application_BeginRequest(object sender, EventArgs e) 
        { 
            if (Response.Cookies["lastaccessed"] == null) { Response.Cookies.Add(new HttpCookie("lastaccessed", DateTime.Now.Ticks.ToString())); } 
            
            if (new DateTime(Convert.ToInt64(Response.Cookies["lastaccessed"].Value)) <= DateTime.Now.AddMinutes(90)) 
            { 
                Response.Redirect("/timedout.aspx"); 
            } 
        } 
    } 
} 

My co-worker asked me why I would want to do something like this, and not just use asp.net's session state in a SQL database, simple, serialization issues with classes we don't control, and that don't need to be persisted between page requests, and permanent sessions. My real code doesn't timeout, that was just an example for begin/end requests. There is of course a database task that clears out sessions that are of a certain age.