ASP.NET Web Applications: Understanding Application-Level Events Throughout the Life Cycle

ASP.NET Web Applications: Understanding Application-Level Events Throughout the Life Cycle

Introduction

Any web developer must possess at least a basic knowledge of the events of a web application. Understanding the events that are present, including how and when they are called, makes the development of dynamic web pages crucially smooth and seamless.

In this blog post, I'll explain the various application-level events that are available in ASP.NET and how you can leverage them to build better web applications. We'll take a deep dive into each event, looking at its purpose, how to use it, and some common scenarios where it can be helpful.

Types of Events

The events in a web application occur at three different levels:

  • At the Application-Level (e.g., Application Start, Application End, etc.)

  • At the Page level (e.g., Page Init, Page Load, etc.)

  • At the Control-level (e.g., Button Click)

In this blog, I will be discussing Application-Level Events. Let's first start by understanding how a web form is returned from the server after the user makes a request.

Life Span of a Web Application

Web forms live for only a moment. After the user sends a request to the server to load the web form, the following process takes place:

  • An instance of the requested web form is created along with the instance of any control (textbox, button, etc.) or variables contained in the web form.

  • Events are processed.

  • HTML is generated and then posted back to the client making the request.

  • The web form is immediately destroyed.

Web applications work on HTTP (Hypertext Transfer Protocol). HTTP is a stateless protocol, which means it does not retain the state between user requests.

HTTP, being stateless, has no provision for the transfer of data:

  • Be it within the same web form across many requests (Get, Post, etc.)

  • Or be it from one web form to another.

How is Data Transferred?

To build a dynamic web application, the transfer of data between states and web forms is crucial.

Transfer of Data between requests (such as Get, Post, etc.) for a single Web Form - When it comes to preserving or transferring data (such as values/status of textboxes, checkboxes, dropdowns, etc.) within a specified web form, View state variables are used as they preserve data across postbacks. By default, the view state of one web form is not available in another web form.

Transfer of Data between Web Forms - When there is a need to transfer data from one web form to another, you can't use view state variables. Instead, the following techniques can be used:

  • Query Strings.

  • Cookies.

  • Session state.

  • Application state.

In this blog, I will focus on Session state and Application State variables and events as they fall under Application-Level Events.

Session State and Application State Variables

Session state variables:

  • Session state variables are available across all pages, but only for a given single session.

  • Session state variables are like single-user global data. This means that only the current session has access to its session state.

  • I'll give you an example of how you can use session state variables:

Let's say I am building a web application that allows users to create and save a shopping cart. To implement this functionality, I can use a session state variable called "cart" to store the items the user has added to their cart during the current session.

In the web application code, I can use the session state variable in the following manner:

// add an item to the cart
if (session["cart"] == null) {
  session["cart"] = new List<Item>();
}

var cart = (List<Item>)session["cart"];
cart.Add(new Item("Product A", 19.99));

// retrieve the items in the cart
var cart = (List<Item>)session["cart"];
foreach (var item in cart) {
  Console.WriteLine(item.Name + " - " + item.Price);
}

In this example, the "cart" session state variable is initialized as an empty list if it doesn't exist yet. When the user adds an item to their cart, the item is added to the list stored in the session variable. Later on, when the user wants to view their cart, the items are retrieved from the session variable and displayed on the screen.

Application state variables:

  • Application state variables are available across all pages and all sessions.

  • Application state variables are like multi-user global data. This means that all sessions can read and write application state variables.

  • I'll give you an example of how you can use application state variables:

Let's say I am building a web application that keeps track of the number of visitors to the site. To implement this functionality, I can use an application state variable called "visitorCount" to keep track of the total number of visitors to the site.

In the web application code, I can use the application state variable in the following manner:

// increment the visitor count
Application.Lock();
int visitorCount = (int)Application["visitorCount"];
visitorCount++;
Application["visitorCount"] = visitorCount;
Application.UnLock();

// retrieve the visitor count
int visitorCount = (int)Application["visitorCount"];
Console.WriteLine("Total visitors: " + visitorCount);

In this example, the "visitorCount" application state variable is incremented each time a new user visits the site. The Application.Lock() method is used to prevent multiple threads from accessing and updating the variable at the same time. When the visitor count is retrieved, it is displayed on the screen.

Session State and Application State Events

Application State Events:

Application events are used to initialize data that needs to be available at all current sessions of the application. Examples are:

  • Application_Start - this event gets fired when your application is not already running and the first request for a webform in the application is made to the web server. You can use this event to perform initialization tasks, such as setting up database connections, registering routes, and initializing Application-Level variables.

  • Application_End - this event is fired when there are no more active sessions and the last session has already expired. You can use this event to perform cleanup tasks, such as closing database connections, releasing resources, and saving Application-Level data.

  • Application_Error - this event is fired when there is an unhandled exception.

Session State Events:

Session events are used to initialize data that needs to be available only for a given individual session and not multiple sessions. Examples are:

  • Session_Start - this event is fired when a new session is started. You can use this event to perform tasks such as initializing Session-Level variables, logging the user's access to the application, and updating the visitor count.

  • Session_End - this event is fired when an existing session ends due to session timeout. You can use this event to perform tasks such as releasing Session-Level resources, updating the visitor count, and logging the user's session activity.

To understand session state variables and events better you have to know what sessions are.

What are Sessions?

A Session is a unique instance of the browser. A single user can have multiple sessions, by visiting the application, with multiple instances of the browser running with a different session id on the machine.

The Global.asax File

In ASP.NET web application, the global.asax file contains the Application-Level Events that I have mentioned previously.

The general format is as follows:

public class Global : HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup  
    }
    void Application_End(object sender, EventArgs e)
    {
        //  Code that runs on application shutdown  
    }
    void Application_Error(object sender, EventArgs e)
    {
        // Code that runs when an unhandled error occurs  
    }
    void Session_Start(object sender, EventArgs e)
    {
        // Code that runs when a new session is started  
    }
    void Session_End(object sender, EventArgs e)
    {
        // Code that runs when a session ends.  
        // Note: The Session_End event is raised only when the sessionstate mode  
        // is set to InProc in the Web.config file. If session mode is set to StateServer  
        // or SQLServer, the event is not raised.  
    }
}

Above I have shown you the general format of how the global.asax file can look.

Now I will present you with an example of the global.asax file:

using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MyApp
{
    public class MvcApplication : HttpApplication
    {
        protected void Application_Start()
        {
            // Code to execute when the application starts
            RegisterRoutes();
        }

        protected void Application_End()
        {
            // Code to execute when the application ends
            ReleaseResources();
        }

        protected void Session_Start(object sender, EventArgs e)
        {
            // Code to execute when a new user session starts
            UpdateVisitorCount();
        }

        protected void Session_End(object sender, EventArgs e)
        {
            // Code to execute when a user session ends
            ReleaseSessionResources();
            UpdateVisitorCount();
        }

        private void RegisterRoutes()
        {
            // Code to register the application's routes
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }

        private void ReleaseResources()
        {
            // Code to release application-level resources
            // For example, closing database connections or disposing objects
        }

        private void UpdateVisitorCount()
        {
            // Code to update the visitor count
            // For example, incrementing a counter in the application state
        }

        private void ReleaseSessionResources()
        {
            // Code to release session-level resources
            // For example, removing session data or closing session-specific connections
        }
    }
}

In this example, the Global.asax file defines a class called MvcApplication that inherits from HttpApplication. The Application_Start event is called when the application starts and registers the application's routes. The Application_End event is called when the application ends and releases any resources that were allocated by the application.

The Session_Start event is called when a new user session starts, and it updates the visitor count by calling the UpdateVisitorCount() method. The Session_End event is called when a user session ends, and it releases any resources that were allocated by the session and updates the visitor count again.

The UpdateVisitorCount() method is a simple example of how you can use application state variables to keep track of the number of visitors to your site. You could define an Application-Level variable to store the visitor count, and then increment it each time a new user session starts or ends.

The ReleaseSessionResources() method is a simple example of how you can release session-level resources when a user session ends. For example, you might want to remove any session data that was stored in memory or close any session-specific database connections.

Conclusion

In conclusion, understanding Application-Level events is crucial for building robust and efficient ASP.NET web applications. The Global.asax file provides a way to handle events throughout the application's life cycle, from the application starting up to individual user sessions ending.

By leveraging these application-level events, you can improve the performance and stability of your ASP.NET web applications, while also adding custom functionality and improving the user experience.

So, make sure to take advantage of the power of application-level events in your next ASP.NET web application project, and unleash the full potential of this powerful technology!