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.
Related
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.
I am developing an ASP.NET MVC 5 application and I need to manage some global parameters, which are basically just a set of key-value-pairs. My requirements are the following:
Initial values are read from a server config file.
Parameters are available in every controller for both reading/writing and adding/deleting (like a new parameter can be added if certain controller is executed).
Parameters should surface subsequent request (either residing in Session or serialized in QueryString).
I should be possible to see and easily manage them (CRUD) using a special admin webpage.
My "brute force" approach for this would be just to implement a static class with List<Tuple<string,string>> to keep the settings, use System.Web.Configuration.WebConfigurationManager to populate initial values, use static properties to store and retrieve the list in a session variable and design a separate controller and view for managing the settings.
But this looks like re-inventing the wheel to me. Is there any (not necessarily full-fledged) pre-existing solution (in ASP.NET, or as a NuGet package) I might rest my efforts upon? Or maybe I am missing something fundamental in ASP.NET?
UPDATE: Depending on the nature of the parameter, some of them might have the lifetime of the Application, whereas some of them are bound to the current user session. Therefore they need to be either preserved in a Session object or "passed through" in every request.
That sounds like the most common approach, I don't see anything wrong with using session variables.
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
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.
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.