Are static class instances unique to a request or a server in ASP.NET?
Asked Answered
B

5

194

On an ASP.NET website, are static classes unique to each web request, or are they instantiated whenever needed and GCed whenever the GC decides to disposed of them?

The reason I ask is because I've written some static classes before in C# and the behavior is different than I would have expected. I would have expected static classes to be unique to each request, but it doesn't seem like that is the case.

If they are not unique to each request, is there a way to allow them to be?

UPDATE:
The answer driis gave me was exactly what I needed. I was already using a singleton class, however it was using a static instance and therefore was being shared between requests even if the users were different which in this case was a bad thing. Using HttpContext.Current.Items solves my problem perfectly. For anyone who stumbles upon this question in the future, here is my implementation, simplified and shortened so that it easy to understand the pattern:

using System.Collections;
using System.Web;

public class GloballyAccessibleClass
{
    private GloballyAccessibleClass() { }

    public static GloballyAccessibleClass Instance
    {
        get
        {
            IDictionary items = HttpContext.Current.Items;
            if(!items.Contains("TheInstance"))
            {
                items["TheInstance"] = new GloballyAccessibleClass();
            }
            return items["TheInstance"] as GloballyAccessibleClass;
        }
    }
}
Benedictbenedicta answered 12/10, 2008 at 2:25 Comment(2)
Just a heads up: If you redirect your request, say, with filterContext.Result = new RedirectResult(...) you will lose your items because a new HttpContext will be created. More details here: #16698101Markusmarl
A related question with a good answer is at https://mcmap.net/q/136604/-static-variables-in-web-applications.Pages
D
156

Your static classes and static instance fields are shared between all requests to the application, and has the same lifetime as the application domain. Therefore, you should be careful when using static instances, since you might have synchronization issues and the like. Also bear in mind, that static instances will not be GC'ed before the application pool is recycled, and therefore everything that is referenced by the static instance, will not be GC'ed. This can lead to memory usage problems.

If you need an instance with the same lifetime as a request, I would suggest to use the HttpContext.Current.Items collection. This is by design meant to be a place to store stuff that you need througout the request. For nicer design and readability, you can use the Singleton pattern to help you manage these items. Simply create a Singleton class that stores its instance in HttpContext.Current.Items. (In my common library for ASP.NET, I have a generic SingletonRequest class for this purpose).

Dichotomize answered 12/10, 2008 at 9:51 Comment(6)
Could you provide a sample of your Singleton pattern involving HttpContext.Current.Items?Raymond
More details about my situation: in my web app, the user will run through a class library of code that uses a shared class property. I want this property to be user specific, but I don't want to have to hand this property around to the different functions. Can the design you mention, handle this properly?Raymond
Please, could you share the SingletonRequest class?Tattler
I do not store any data in static class. I use static class only for getting data or setting data as a data layer. So is there any problem?Psychosurgery
"static instances will not be GC'ed before the application pool is recycled, and therefore everything that is referenced by the static instance, will not be GC'ed" -- Is there any source for this, because it doesn't make any sense and conflicts with what I've read elsewhere. When the AppPool is recycled the related App Domain is completely torn down and GC'd. When this happens any related static instances will also be GC'd because their root (the AppDomain) is gone. As part of the pool recycle a new AppDomain is created and it's associated static instances are initialized.Compost
@Nick: I had to read this twice to understand what was said. But basically just append to that sentence "..., until the recycle finally happen due to inactivity or request limits reached" The point made was that your static object instances in static members stay in memory basically for as long as the App Pool is running. Basically hogging active memory.Amulet
L
31

Static members have a scope of the current worker process only, so it has nothing to do with requests, because different requests may or may not be handled by the same worker process.

  • In order to share data with a specific user and across requests, use HttpContext.Current.Session.
  • In order to share data within a specific request, use HttpContext.Current.Items.
  • In order to share data across the entire application, either write a mechanism for that, or configure IIS to work with a single process and write a singleton / use Application.

By the way, the default number of worker processes is 1, so this is why the web is full of people thinking that static members have a scope of the entire application.

Lazybones answered 20/8, 2013 at 12:9 Comment(1)
I would like to add that the default worker process number of "1" is a manual configuration setting in IIS, and you will mostly leave it at one 99% of the time, but in the future, with large request volumes, you may want to increase this. You configure this on your App Pool advanced settings.Amulet
G
13

Since the types are contained in an app domain, I would expect static classes to be present as long as the app domain is not recycled, or if the request gets served by a different app domain.

I can think of several ways to make objects specific to a particular request depends on what you want to do, for e.g. you could instantiate the object in Application.BeginRequest and then store it in HttpRequest object so that it can be accessed by all objects in the request processing pipeline.

Git answered 12/10, 2008 at 2:30 Comment(0)
O
4

If they are not unique to each request, is there a way to allow them to be?

Nope. Static members are owned by the ASP.NET process and shared by all users of the Web app. You'll need to turn to other session management techniques such as session variables.

Omar answered 12/10, 2008 at 2:57 Comment(0)
F
2

Normally static methods, properties and classes are common at the Application level. As long as the application lives, they are shared.

You can specify a different behaviour by using the ThreadStatic attribute. In that case they will be specific to the current thread, which, I think, is specific for each request.
I would not advise this though as it seems overcomplicated.

You can use HttpContext.Current.Items to set stuff up for one request, or HttpContext.Current.Session to set stuff up for one user (across requests).

In general though, unless you have to use things like Server.Transfer, the best way is basically creating things once and then passing them explicitly via method invocation.

Flyspeck answered 12/10, 2008 at 10:2 Comment(3)
Jon Skeet shows us that ThreadStatic is never safe in ASP.Net #4791708Vietnam
Down-voted since a thread is not unique to a request. Please, remove this AnswerWaac
Mentioning Session vs Request in these answers are very important since the reader should also understand there is an intermediate state between Static members and HttpContext.Current.Items (for each Request), called the Session, and this answer points that out elegantly.Amulet

© 2022 - 2024 — McMap. All rights reserved.