Does asp.net MVC have Application variables?
Asked Answered
S

6

48

I am busy converting a web application to MVC and have some information saved to Application variables used across multiple tenants/accounts to make things a bit more efficient.

I realise the point of MVC is to keep things as stateless as possible, Sesion State obviously makes sense to have and exists in MVC but we dont want to just convert Application to Session variables as we would rather have something more global and more secure. Do MVC applications have Application Variables? I have seen some examples where caching is used? Is this now standard and How robust/secure is this compared to Application/Session State?

Shut answered 15/2, 2010 at 14:28 Comment(0)
F
104

Yes, you can access Application variables from .NET MVC. Here's how:

System.Web.HttpContext.Current.Application.Lock();
System.Web.HttpContext.Current.Application["Name"] = "Value";
System.Web.HttpContext.Current.Application.UnLock();
Fortson answered 17/9, 2010 at 7:53 Comment(6)
Why calling Lock and Unlock? Is it also necessary when reading a previously set value?Salinas
@Salinas it's to help prevent against race conditionsHirsh
@ZachM. What kind of race could happen here? Possibly create 2 Application variables with same name? Other than that, I don't see much else could get in a race condition, and this would be something I would expect the set operation to handle internally.Salinas
I was simply stating the reason for lock and unlock, if you have an application with multiple users this could happen. Application wide variables are available out of session from my understanding.Hirsh
One example is that you have multiple users accessing your site and you want to run some resource intensive code once every few minutes, but no more. The application variable is available across sessions, so you use the application variable to track the last time someone ran the resource intensive code. You lock the application variable, check the time it was last run, and if it is time to run the code again, you update the application variable to the current time, unlock the variable, and run the resource intensive code.Fortson
@Zach M - Session is specific for every user, you can't access other user session variableSouthern
A
7

Session state or the Cache are better choices. They are mockable in MVC and are designed to store session and application-scoped data.

Static classes seems like a popular choice here. However static classes create dependencies between your types and make versioning/testing harder. Its also a bit of an odd pattern to use in a framework that is designed to break apart these kinds of dependencies. For instance, the standard ASP.NET framework is riddled with statics and sealed types. These are all replaced with mock-able instances.

"Secure" is a bit unclear in this context. Exactly what do you mean by "secure?"

Anklebone answered 15/2, 2010 at 14:35 Comment(4)
Of course for optimal decoupling, testing etcetera one should store them in an ordinary class and put a instance that class in a the IoC-container.Drummond
@svinto that all depends on the rest of the design. IOC isn't configuration. You can configure for IOC but that's more about what type to use in this situation, not what color to use on the header background, for instance.Anklebone
Voted up! Static classes have a lot of the same problems as global variables and big S Singletons. They are tightly coupled, difficult to test and can have concurrency issues. If you do use static classes you should make all properties readonly!! Better to store your variables in a data file (XML, JSON, YAML) or a database and then pull them into cache. This also has the benefit of letting you change your configuration without recompiling. IoC could be useful if you think you might change the data source and want to be able to switch between different classes to load the data into cache.Nevlin
Session State is per request. Application state, as the OP wants, is the same across all requests. Cache is closer, but is more appropriate for caching values which require heavy workload to create, but may change, and could be updated after a given timeout. HttpContext.Current.Application is the right answer here.Ahern
R
4

I implemented something like below as an Extension for Global state variable. I put things like Site title,Service Endpoints, authorized roles

public static class ApplicationStateExtension
 {
    public static T GetSetApplicationState<T>(this HttpApplicationState appState, string objectName, object objectValue = null, int syncCheckMinutes = 0)
    {
        T retVal = default(T);
        appState.Lock();
        if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
        {
            appState[objectName + "LastSync"] = DateTime.Now;

            if (objectValue != null)
                appState[objectName] = objectValue;
        }
        if (appState[objectName] != null)
            retVal = (T)appState[objectName];
        appState.UnLock();
        return retVal;
    }
    public static object GetSetApplicationState(this HttpApplicationState appState, string objectName, object objectValue = null, int syncCheckMinutes = 0)
    {
        object retVal = null;
        appState.Lock();
        if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
        {
            appState[objectName + "LastSync"] = DateTime.Now;

            if (objectValue != null)
                appState[objectName] = objectValue;
        }
        if (appState[objectName] != null)
            retVal = appState[objectName];
        appState.UnLock();
        return retVal;
    }
    public static void SetApplicationState(this HttpApplicationState appState, string objectName, object objectValue, int syncCheckMinutes = 0)
    {
        appState.Lock();
        if (appState[objectName + "LastSync"] == null || DateTime.Now.Subtract(((DateTime)appState[objectName + "LastSync"])).TotalMinutes >= syncCheckMinutes)
        {
            appState[objectName + "LastSync"] = DateTime.Now;
            appState[objectName] = objectValue;
        }
        appState.UnLock();
    }
    public static object GetApplicationState(this HttpApplicationState appState, string objectName)
    {
        object retVal = null;
        appState.Lock();
        if (appState[objectName] != null)
            retVal = appState[objectName];
        appState.UnLock();
        return retVal;
    }
    public static T GetApplicationState<T>(this HttpApplicationState appState, string objectName)
    {
        T retVal = default(T);
        appState.Lock();
        if (appState[objectName] != null)
            retVal = (T)appState[objectName];
        appState.UnLock();
        return retVal;
    }
}

So I can set them from Global.asax.cs something like this

Application.SetApplicationState("UISiteTitle",paramHelper.GetUIConfigXML<XMLParams.UISiteOptions>("UISiteOptions")
                .SiteOptionCollection.Where(v => v.name.Equals("title", StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault().value););

or

var uiPermissions = Application.GetSetApplicationState<XMLParams.UIPermissions>("UIPermissions", paramHelper.GetUIConfigXML<XMLParams.UIPermissions>("UIPermissions"), 30);
Rabe answered 3/4, 2013 at 17:45 Comment(1)
What's the point of "LastSync" in this? Is it necessary for generic use?Blew
O
3

You can declare Application variables in Application_Start like this:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    RouteConfig.RegisterRoutes(RouteTable.Routes);

    var e = "Hello";
    Application["value"] = e;
}

To access this on controller write:

string appVar = HttpContext.Application["value"] as string;
Obtrusive answered 14/2, 2017 at 9:54 Comment(0)
D
2

Make a static class?

Drummond answered 15/2, 2010 at 14:29 Comment(8)
I find static classes work great under the MVC context, it also helps you get away from the app/session state idea.Wagers
@jeremy except the session state is specifically updated for use in MVC. I'd definitely support "getting away from" it in order to reduce the amount of state stored on the server, but it definitely still has a place in the framework.Anklebone
application scope and static class are very different things. Though they can be interchanged in some situations.Brockington
Implementing application variables as static classes makes them difficult to mock in unit testsAhern
what if i want to store an initialized object?Shoulders
Static classes can work, but be careful about thread safety for any static variables that might be modified by multiple requests.Either
how can you be sure that iis or whatever host you are running in doesn't flip threads on you? in which case your static things will be reset.Rachael
Static classes are a very bad idea if you want to run multiple servers or processes.Kithara
B
0

Do they have Application Variables? Yes, MVC is a framework that sits on top of the normal asp.net framework.

I would however create a static class that uses a cache store as it's backing.

Bola answered 15/2, 2010 at 14:31 Comment(1)
hi @used2could can you please tell the benefits of using static class backed with cacheLeal

© 2022 - 2024 — McMap. All rights reserved.