asp.netwebformshttpapplicationhttpapplicationstate

Can Application property of HttpApplication class be used to calculate current Active Users?


I am using the following code in the ASP.NET web forms Global.aspx page to count the number of current active users. It does work when I do local testing.

Understanding is that Application is an Application-level variable and can be accessed at the application level. So value stored in one session will be available in other sessions.

<%@ Application Language="C#" %>  
  
<script runat="server">  
  
    void Application_Start(object sender, EventArgs e)   
    {  
        // Code that runs on application startup  
        Application["TotalOnlineUsers"] = 0;  
    }  
      
    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  
        Application.Lock();  
        Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] + 1;  
        Application.UnLock();  
    }  
  
    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.  
        Application.Lock();  
        Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] - 1;  
        Application.UnLock();  
    }  
         
</script>

But while going through this link https://learn.microsoft.com/en-us/dotnet/api/system.web.httpapplication?redirectedfrom=MSDN&view=netframework-4.8, it says that member variables can be used to store per-request data.

Based on this statement and below complete paragraph, there can be multiple instances of HttpApplication for a single application, if not application will be super slow as one HttpApplication instance can process only one request at one point in time

Because of this, each HttpApplication will have its own Application variable and the count will be saved at HttpApplication level.

Instances of the HttpApplication class are created in the ASP.NET infrastructure, not by the user directly. One instance of the HttpApplication class is used to process many requests in its lifetime. However, it can process only one request at a time. Thus, member variables can be used to store per-request data.

An application raises events that can be handled by custom modules that implement the IHttpModule interface or by event handler code that is defined in the Global.asax file. Custom modules that implement the IHttpModule interface can be put in the App_Code folder or in a DLL in the Bin folder.

So, to get the exact count without any chance of miscalculating, should I use static variables?


Solution

  • I believe your code will work correctly, assuming you’re using InProc session state and aren’t running in a Web farm.

    Confusingly, the word “application” can have three different meanings:

    1. Your Web application (that is, the whole Web site)
    2. One of the multiple HttpApplication instances that serve requests to your Web application
    3. The HttpApplication.Application property

    When the documentation says that the Application property returns “the current state of an application,” it means your Web application, not an individual HttpApplication instance.

    It’s true that if you add a member variable to your Global class (which inherits from HttpApplication), then the member variable won’t be shared across HttpApplication instances. But the Application property is special: it returns the same HttpApplicationState object no matter which HttpApplication instance you use to access the property. Hence, any values you add via the Application property will be shared across all HttpApplication instances. (And that’s why you must call Lock and UnLock to synchronize access; you wouldn’t need to do so if the HttpApplicationState object weren’t shared.)