Destroy Static Variables in C#/ASP.NET - c#

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

Related

ASP.Net Razor C# Variables Accessible to All Pages

For starters, please forgive me and please correct me on my terminology. I am quite sure of the correct words to use for what I am trying to accomplish.
I have been given the task of building an ASP.Net Razor web site. It is something new to me. I am very proficient in PHP and ASP Classic. What I need to be able to figure out is how to declare a variable that is accessible everywhere. I do not know if in the .net world you call it a global variable or application variable or something else. But, here is how I would do this in Classic ASP.
In Classic ASP, I would have a file named VarFunct.asp. It would be the file that I declare my variables and have various functions I would access from anywhere. I would include the VarFunct.asp file on all of my pages. Anyway this is what I am really trying to do (written in how I would do it in Classic ASP)…
SelLoc = Request("SelLoc")
If Len(Trim(SelLoc)) = 0 Then
SelLoc = "All"
End If
In this case, Request("SelLoc") could be Request.QueryString or Request.Form. Then anywhere in my website I could use the variable SelLoc. So, in short... I need to be able to set a variable. Check to see if it is set by Request.Form, if not, check Request.QueryString, if not set the value to “All”. How do I write this? And where do I put it?
When I created the website using Visual Studio 2012, I selected ASP.NET Web Site (Razor V2).
This seems like it should be such a basic fundamental task of any website that has any kind of server side programming, but trying to find information and documentation online is near impossible, but probably because I am not using the correct terms for my question. I have not found any Razor tutorials that talk about setting variables that can be used globally across the website.
If someone could please help me out here by either telling me what I need to do or point me to a good tutorial, that would be great.
what you are looking for is called Static Class/Member
This will allow you to store and share data for the whole application.
BUT! since web server is multi-threaded, you wouldn't want to do this or else you might run into the case where the data is overwritten by another request before you finished the current one.
If you need to pass data from controller to your View you can use ViewBag dynamic object
If you need to use the data anywhere else (for example in a helper class) then do
HttpContext.Current.Application["VariableName"] = something
It is basically a dictionary and each request will have a different Application object
There are several ways of doing this.
For your example I would assume that this particular variable can be different for different users that are using the application at the same time. This is more of a Session scope than Application scope.
In this case you could simply use inheritance and make a base controller and/or base view model class that all your other controllers and/or view models inherit from. This way you can pass it back and forth between the view and controller and read/update it whenever you need to.
You could also use the Request and HttpContext and Session objects that are built into asp.net, if they fit your need. A brief overview of some of their functionality can be found here: https://learn.microsoft.com/en-us/aspnet/web-pages/overview/api-reference/asp-net-web-pages-api-reference --- google searching specific ones yields tons of results.
If you truly want Application scope, you can of course use a static class for you utilize static methods. Then you don't need to include the class in every other class, but you would need to fully name qualify the method when you call it.
I would not recommend static variables at this level though. I can't imagine very many things that would need to change for every single user that you would change while the application instance is running. Most of these sorts of items that we use are caches (generally db lookups and such, that we don't want to retrieve from the db each time, and RARELY get updated). If you utilize caches, be very aware of your thread safety when updating them. Here is an msdn on caching: https://msdn.microsoft.com/en-us/library/aa478965.aspx --- Or application configuration settings, like the application environment. We pull most of those from a config file, and they are read only, we don't change them within a running instance of the application.

use of Application State Variables and Application Level Events

When talking about state variables, I know the use of View State variables and Session State Variables. View state variables when we need to preserve data accross page postback. Session State variables are used to store username, role of the user, values we need to access throughout a session.
But what is the importance of Application State Variables in real time projects ? What type of values should be stored in these variables ?
What is mean by Application Level Events, what is the real time use of these events?
Mostly we use Application State Variables in Application Level Events in Global.asax file.
Please can you share how and where can we use these variables. How have you utilized the application state variables in your projects?
I've used application state variables as a sort of rudimentary cache on very small production apps that do not do much. But outside of that, I have not found much use for them. E.g. it's pretty straight forward implementing a caching framework; also these variables become quite useless when working in a server farm.
Application level events are basically those events that exist in your global asax like Application_Start, Application_BeginRequest, Application_Error etc. Even then I don't use application state variables in these events - there is always something better to use, like configuration files.
Lastly, to keep your code clean its better to encapsulate these variables in some sort of class (preferably an abstract class that is swapped out using DI) so I see little benefit of using them outside of quick-and-dirty projects.

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

How to make requests to servers stateful even better UNIQUELY stateful?

So I am having problems saving collections unique across tabs/browser (tabs really).
Using static variables to store data after the callback in ASP didn't work so well because all browsers could read from it and modify the variables.
Using session variables didn't work so well because while it successfully made the collection unique across browsers - it wasn't unique across tabs. So one Mozilla tab could modify a the collection in a session variable (the collection changes) - the user will get a nasty surprise when using another Mozilla tab when accessing the collection again - unfortunately the SAME collection - something like a dirty read.
So the problem is - how can I make collections across tabs/browsers stateful but uniquely stateful so that each can have their own unique collection and can modify it freely.
The problem as I see it here is one tab continually makes an ajax request which always recreates the controller object which means it will never be unique.
Another idea was to save a reference to this collection in javascript - and then pass this reference back and forth during each request - The problem is how can I do it without serializing/deserializing which kind of defeats the point of just saving the reference :(
Any ideas are welcome.
Methods that didn't work: Session, Application/Static (haven't tried Application but it seems to behave the same way).
Will ViewState work? It doesn't seem to save data however :'(
Replace the default route with a custom route which adds a GUID to the uri. And use that GUID to load the session.
I've made an example in my blog just for you: http://blog.gauffin.org/2012/02/get-a-unique-session-in-each-browser-tab/
You can store information into window.name, which should be unique per tab, since each tab is a different window.
Demo: http://www.thomasfrank.se/sessionvars.html

Using HttpContext.Current.Application to store simple data

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.

Categories