Using HttpContext.Current.Application to store simple data - c#

I want to store a small list of a simple object (containing three strings) in my ASP.NET MVC application. The list is loaded from the database and it is updated rarely by editing some values in the site's admin area.
I'm thinking of using HttpContext.Current.Application to store it. This way I can load it in the Global.asax:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
HttpContext.Current.Application["myObject"] = loadDataFromSql(); // returns my object
}
And then can easily reference it from any controllers or views as needed. Then in the event, the admin area calls the updateMyObject controller action, I can just update the DB and load it in again and replace HttpContext.Current.Application["myObject"].
Are there any cons to doing this? It seems like it will work fine for what I am trying to achieve, however does anyone know of a better way to do this, assuming there is some major disadvantage to the method I've laid out?

What you actually do is Caching, and it's great, since you reduce calls to an external storage (a database or a file, whatever). The trade-off is memory usage, of course. Now, almost any modern web framework, including ASP.NET, includes some kind of a caching mechanism. Either you use it, or you use some kind of a global variable.
Storing data in ASP.NET's built-in Cache object has some significant advantages, since this mechanism actually checks the memory usage and removes the cached data according to some rules.
However, if the data you want to cache is intensively used across the application, and its size is not too large (say, smaller than 1 MB), you may want to store it in as a global variable.
In ASP.NET, global variables are achieved by either using the Application object, like you described in your question, or by writing public static properties/fields in an internal/public class.
Here's my solution to static properties. Note that I use a locking object, to protect the inner data from corruption. It looks like this:
public class WhateverClass
{
private static object theLocker = new object();
private static YourDataType theData;
public static YourDataType TheData
{
get
{
lock (theLocker)
{
return theData;
}
}
set
{
lock (theLocker)
{
theData = value;
}
}
}
}
The usage is very simple:
First time, in Application_Start:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
WhateverClass.TheData = loadDataFromSql();
}
In any controller:
var myData = WhateverClass.TheData;
This approach is better because you have type safety, since this public static property can be explicitly declared with the exact type. In addition, this kind of storage is more testable since it doesn't depend on the web context.
HTH!

HttpContext.Current.Application is essentially a hangover that is needed for backwards compatibility with classic ASP. It's essentially a static Hashtable with classic ASP locking semantics (Application.Lock / Application.UnLock).
As a weakly-typed Hashtable, you will need to cast objects you retrieve:
MyObject myObject = (MyObject) HttpContext.Current.Application["myObject"];
In an ASP.NET application that is not a migration from classic ASP, I would prefer using other standard .NET stuff, such as:
A static field, using .NET locking semantics if you need locking (e.g. the C# lock keyword, or a ReaderWriterLockSlim instance, depending on your requirements):
static MyObject myObject = LoadFromSql();
The ASP.NET Cache - which has rich functionality for managing expiration, dependencies, ...

Yes, using HttpContext.Current.Application will work fine for what you are doing. No problems.
HttpContext.Current.Application is simply a reference to the static global HttpApplicationState object in .NET for your Web Application, of which there should be one global instance per web application. By storing data there, you provide fast, thread-safe access to your global variables. Be sure to lock them when updating values, as in this example:
System.Web.HttpContext.Current.Application.Lock();
System.Web.HttpContext.Current.Application["WebApplicationPath"] = MyWebApplicationPath;
System.Web.HttpContext.Current.Application.UnLock();
As others have mentioned, you can also create a series of static classes in your App_Code or other folder and there store global static values as well as your HttpContext.Current.Application values, where they can be safely checked for values or updated from the database, or update and check each other, working in tandem. I usually create a static global class to assist in the management and retrieval of the Application variables I store. In this way you have both the state dictionary of the HttpApplicationState class and the web application static objects working together to share and maintain global values. (Keep in mind each static class is assigned per worker process and there may be as many as 10 WP on average by default on many IIS web servers/web applications. So keep data in static types to a minimum.)
Keep in mind as some mentioned server farms do not share Application state. There are many ways to manage this. I'm not a fan of cache because of the ways in which it can expire, fail, become stale, or get corrupted. A simpler solution is to simply use use the database and URL querystrings to communicate across servers and maintain state. Good luck!

If you're deploying to a single web server the approach would work. Consider the Cache object for this as it provides more options for expiration if you need such functionality. (See a comparison, albeit an aged one, here.)
If you're ever going to deploy to a web server farm or equivalent you should use memcached or another web farm friendly caching mechanism. Both the Application and Cache objects only typically exist in a single server context; if your user could be hitting multiple web servers during their session (and the cache needs to be identical) you'll need a shared cache that can be seen from each of the potential web servers.
Regardless of which path you take you will need to invalidate/reload your cache whenever the underlying data changes, which is custom code that varies by app.
This approach works well and can speed things considerably but it's a bit more work than you may realize at first glance...

Application_Start really only gets fired on App Pool Recylce's, IIS Resets or reboots. If your updating these values that infrequently, why not store them in your web.config and access them that way?
That being said, I don't think there is anything wrong with your approach. Though more typically I've seen people using config files for rarely changed values.

Related

Best way to store data (single object) in Web API project without database

My project group and I are to develop a generic workflow system, and have decided to implement a single Node (a task in the workflow) as a C# Visual Studio Web API project (Using the ASP.NET MVC structure).
In the process of implementing a Node's logic, we've come across the trouble of how to store data in our Node. Our Node specifically consists of a few lists of Uri's leading to other Nodes as well as some status/state boolean values. These values are currently stored in a regular class but with all the values as internal static fields.
We're wondering if there's a better way to do this? Particularly, as we'd like to later apply a locking-mechanism, it'd be prefereable to have an object that we can interact with, however we are unsure of how we can access this "common" object in various Controllers - or rather in a single controller, which takes on the HTTP requests that we receive for ou Node.
Is there a way to make the Controller class use a modified constructor which takes this object? And if so, the next step: Where can we provide that the Controller will receive the object in this constructor? There appears to be no code which instantiates Web API controllers.
Accessing static fiels in some class seems to do the trick, data-wise, but it forces us to implement our own locking-mechanism using a boolean value or similar, instead of simply being able to lock the object when it is altered.
If I am not making any sense, do tell. Any answers that might help are welcome! Thanks!
Based on your comments, I would say the persistence mechanism you are after is probably one of the server-side caching options (System.Runtime.Caching or System.Web.Caching).
System.Runtime.Caching is the newer of the 2 technologies and provides the an abstract ObjectCache type that could potentially be extended to be file-based. Alternatively, there is a built-in MemoryCache type.
Unlike a static method, caches will persist state for all users based on a timeout (either fixed or rolling), and can potentially have cache dependencies that will cause the cache to be immediately invalidated. The general idea is to reload the data from a store (file or database) after the cache expires. The cache protects the store from being hit by every request - the store is only hit after the timeout is reached or the cache is otherwise invalidated.
In addition, you can specify that items are "Not Removable", which will make them survive when an application pool is restarted.
More info: http://bartwullems.blogspot.com/2011/02/caching-in-net-4.html

Destroy Static Variables in C#/ASP.NET

I am forced to use static variables because of the asp.net execution path. I have to have the same variables on the master page as well as the page being called. Static variables make it very easy to carry over variables because they remain static. Unfortunately these variables hang in the ether of memory because the app hasn't actually "exited". Is there a way to destroy these variables when I finished used them? I looked into
IDisposable
but its implementation is not... clean. Is there a way to destroy variables when the page finishes rendering?
I am forced to use static variables because of the asp.net execution path. I have to have the same variables on the master page as well as the page being called. Static variables make it very easy to carry over variables because they remain static.
You aren't "forced" to use static fields just to share data between a master page and its content page. You probably don't want to either: static fields will be shared between all requests from all users of your application, which means they need to be thread-safe and limited to data that is shared between all users.
There are many techniques to share data between master and content page. For example, you could use the HttpContext.Items dictionary, which exists only for the duration of a single request.
For anyone looking for a way to "pretend" static variables, here is how you can go about it:
public static Datatype data
{
get
{
return (Datatype)HttpContext.Current.Items["DATA"];
}
set
{
HttpContext.Current.Items["DATA"] = value;
}
}
As far as I understand this doesn't necessary solve the "kill static" values, but it should avoid any data collisions caused by static variables. I had my entire project referencing the static variable and changing it would of created more messy code than should be seen. This way, when the call goes out to get "DATA" from your static object, it doesn't grab whatever pointed at but rather uses the context list which gets killed after and is unique to your session.
You can set them to null. If you're using ASP.Net WebForms you can do this inside the Page.Unload event handler.
You should avoid using static properties in your master page and use Session[""] variables, they will be destroyed when the user ends the session.
Without knowing your setup, and thinking in a future of cloud environment as well, where you can have more than one server answering user requests and, you have no idea if the same server will answer all the requests of that user or the load balancer ask the other servers to continue, I would, as I currently do, give you 2 options
Before the options, in a Web Environment, it is good pratice to stop using Sessions or Static variables (for the reason above)
Use cookies
Why not use a cookie to pass value from one place to the other and when consumed, simply write the expiration data back one year and the cookie is gone!
Use MemCached
I always have a Cache layer between my application and the database, and it's the best way to keep values, not only from the database to provide to all users, but a good way to keep variables when we need cross application.
MemCached is free and runs fine on windows, plus there are several Cloud Services that offer this in their servers

Static Repositories - Workaround

First, some background. We have recently taken on a large MVC3 project. The project was pretty much ready to go live some time ago, then the client decided they wanted to re-theme the whole website and add a load more functionality. They employed us to re-theme the site, finish off the remaining functionality and deploy it.
Generally it is built using a very clear, ordered approach, with one repository for each database table and a clear service layer, however there are some oddities that are making me slightly uncomfortable. The main oddity that keeps on nagging at me is that every single repository and service in the application is completely, 100% static (yes, including methods that write to the db). Of course, this doesn't allow for unit testing, however a greater concern is the potential bottlenecks and threading issues that will cause when the application comes under a heavy load. I am already seeing some unexplained delays in processing requests on the stage server, and that is with a trickle of testing traffic.
The application is so huge that rebuilding it to use IOC/instantiated-per-request repositories is pretty much out of the question.
What can I do to avoid potential threading issues upon deployment? Could i use a connection pool and borrow a db connection each time a write needs to happen?
Thanks in advance :)
Edit - here is some of the code that creates an instance of the entity model. Each static method calls this 'DemoEntities' method to obtain an instance of the entity model, which it then uses to execute the db commands. I can see here that, though the method is static, it is actually checking the HttpRequest for a pre-existing instance and creating one if it doesn't already exist. As such, I think we'll be ok.
public static DemoEntities DemoEntities
{
get
{
if (HttpContext.Current != null && HttpContext.Current.Items["DemoEntities"] == null)
{
HttpContext.Current.Items["DemoEntities"] = new DemoEntities();
}
return HttpContext.Current.Items["DemoEntities"] as DemoEntities;
}
set
{
if (HttpContext.Current != null)
HttpContext.Current.Items["DemoEntities"] = value;
}
}
`
Pat
I assume here that your repository classes only contain static methods, not any static state.
The benefit of stateless static classes is that they can be safely turned into regular classes with default parameterless constructors and no concerns over their life-span. It would then be a simple case to extract an interface for testing purposes.
Whenever you need to talk to a repository, simply instantiate one.
Unless the application is doing something with shared state during repository use, you should not need to be concerned about multi-threaded access. The database itself is responsible for handling many concurrent calls.
Currently all bottlenecks and threading issues are potential, sometimes our educated guesses at what could possibly go wrong are themselves wrong - especially so with multi-threading. The slow down might simply be because the database doesn't have the grunt to cope with too many requests.

Global Class to access Variables

We like to have a global instance of a class and would like to access across the application (in different forms etc)
What are the different possiblities? (other than static class).
It sounds like you want the Singleton pattern. Depending on your application you want to be careful though. You only get one instance of it, and this can cause unexpected behaviors with multiple threads etc. (there are other drawbacks too, my main point is that you have to look at the downsides of the pattern also).
C# patterns: http://www.dofactory.com/Patterns/Patterns.aspx
singleton.
Or perhaps (singletons are frowned upon) you could do something with an IoC.
This generally hints that you're doing something wrong though.
You could use ASP.NET Application State.
Application state is a data repository
available to all classes in an ASP.NET
application. Application state is
stored in memory on the server and is
faster than storing and retrieving
information in a database. Unlike
session state, which is specific to a
single user session, application state
applies to all users and sessions.
Therefore, application state is a
useful place to store small amounts of
often-used data that does not change
from one user to another.

Using a static variable to cache data

We're developing a .NET 3.5 Windows Forms app, using LINQ to SQL and MVP. We have a DataRepository class for retrieving data:
public class DbUserRepository : IUserRepository
{
private IList<UserName> _users;
public IList<UserName> GetUserNames()
{
if (_users == null)
{
// retrieve _users from DB
}
return _users;
}
In order to cache the list of users across all instances of the DBUserRepository, we were going to use the Enterprise Library's Caching Application Block.
But it occured to me, couldn't I just make _users a static member? For some reason that seems like an "old school" way, but it works. Are there any downsides to doing this? Is this considered bad design?
private static IList<UserName> _users;
Thanks
The biggest down-side to doing this is exactly due to what static means; although you can have many DbUserRepository objects, they will always only share one _users variable. Cases where this causes problems:
If your app ever becomes multi-threaded, and you want each thread to have its own distinct user repository (whether or not this is a concern depends on what the repository means in the context of your system)
Unit testing the DbUserRepository class becomes trickier, because if you run multiple unit tests on this class, they will carry state along with them from test to test, meaning that the test-run becomes order dependent... which is pretty undesirable
for simple caching I think static variable is fine, just need to be a bit careful about using locks to protect multiple threads accessing the _users variable. However, a better approach might be using ASP.NET Cache class. I know it is in the System.Web namespace but you can use it outside of ASP.NET application too.
Couple of things to consider.
Thread Safety of initializing the variable
AppDomains. Static variables are local to an AppDomain instance. So if you have multiple AppDomains running you will have multiple instances of the cache
These may or may not be of interest to your application. Likely not, but worth noting.
If you do ever need more than one of them, you'll have to go to extra effort to excise the static one from your code and start passing it around all over the place.

Categories