I'm designing a new ASP.NET website (ASP.NET is somewhat new to me so forgive stupid questions) and I was wondering about the life time of an object that I would instantiate in the Global.asax's Application_Start event (i.e. new myClass()). I would refer to the object through a static pointer somewhere.
The reason why I was thinking of doing this was to create a master object for the running ASP.NET application that would track some pieces of information per user (browser), even though I'm storing much of the info in my database. In other words, I wanted to use an array of sessions indexed by a user key, and this array would be an element in myClass that, as mentioned above, gets instantiated in the Global.asax's Application_Start event. I'll regularly trim my array to account for users who have gone off or haven't done anything after NN minutes.
Or, is this just nuts because objects instantiated during the application's life are not reliable in terms of lifetime.
Thanks in advance!
Kind regards,
Derek
Why not use the application cache?
Unfortunately, msdn appears to be down right now, but the link is
http://msdn.microsoft.com/en-us/library/system.web.httpcontext.cache.aspx
It is accessible in your asp.net site through the Context property of the current HttpApplication.
Where you create the object doesn't matter, what matters is where you store the reference to the object.
If you put the reference in a static variable, the object will survive as long as the application is running.
Using static variables in a web application can have its uses, but you have to be careful as a web application is multi threaded. If you change any data in the object, you have to synchronise the access to the data, so that only one thread at a time can access it.
Related
I am in a situation where requirement is to keep an application level object in web api which can be accessed by all requests. I know one can use HttpContext.Current but that is not required since HttpContext is only for the liftime of request. I need a solution where i can keep an object that all requests can access and update as required.
Use a static class to hold your application level objects. static classes and static data members are created once for the application lifetime and all ASP.NET requests can access them.
I learnt it the hard way. Some time back, I mistakenly created a static field to hold customer-specific database connection string, in a ASP.NET Web API project and it became a mess. On each customer's login it was being set (overridden) in the code and the requests from the previously logged customers were using this newly set static SQL connection string for their queries. It was an embarrassing situation when customer's inadvertently saw each other's data.
You could use SessionState (per session).
I.e.
Session["YourDataKey"] = ApplicationLevelObject;
And then check the session state variable on each request that requires it.
However if you require the object for longer, I.e. every single user session, then I would suggest persisting your object to a database. You could use an ORM such as Entity Framework.
Cheers
We're writing a class we'll use in our asp.net site. This class will pull down some json using HttpClients and such, and use it to provide information to other clients.
Some of this information will change very infrequently and it doesn't make sense to query for it on each client request.
For that reason I'm thinking of making a static constructor in this new class for the slow-changing information and stashing the results in a few static member variables. That'll save us a few HttpRequests down the line-- I think.
My question is, how long can I expect that information to be there before the class is recycled by ASP.Net and a new one comes into play, with the static constructor called once more? Is what I'm trying to do worth it? Are there better ways in ASP.Net to go about this?
I'm no expert on ASP.Net thread pooling or how it works and what objects get recycled and when.
Typical use of the new class (MyComponent, let's call it) would be as below, if that helps any.
//from mywebpage.aspx.cs:
var myComponent = new MyComponent();
myComponent.doStuff(); //etc etc.
//Method calls like the above may rely on some
//of the data we stored from the static constructor call.
Static fields last as long as the AppDomain. It is a good strategy that you have in mind but consider that the asp runtime may recycle the app pool or someone may restart the web site/server.
As an extension to your idea, save the data locally (via a separate service dedicated to this or simply to the hard drive) and refresh this at specific intervals as required.
You will still use a static field in asp.net for storing the value, but you will aquire it from the above local service or disk ... here I recommend a System.Lazy with instantiation and publication options on thrread safe (see the constructor documentation).
I am trying to understand the various ways of storing and instantiating Application (i.e. objects available to every user) and Session level (objects created and available to users only for their session) variables. Also, how does OWIN fit into all of this?
Global.asax.cs - This can contain a bunch of different methods. I believe that Application_Start is only called during the first request. However, there are a few candidates here for methods to populate session level variables (e.g. Session_Start and Application_BeginRequest). What is the standard way of doing this?
There is also the Startup class used by OWIN. I get that OWIN lets you store Application level variables, but why wouldn't you just use the HttpApplicationState Application variable accessible from Global.asax.cs to accomplish this? Also - can OWIN handle Session variables?
"I believe that Application_Start is only called during the first
request."
Only for the first request after calling the web application. For instance, this is the case after deploying, ApplicationPool Recycling, restarting or coming out of sleep.
Let's assume 3 users visit your web application. Application_Start will only be called for one of them, specifically the first one that visits it. Therefore it is not suited for populating user-specific session values.
However, there are a few candidates here for methods to populate session level variables (e.g. Session_Start and Application_BeginRequest). What is the standard way of doing this?
In the past I've worked with Session_Start to initialize user-specific session values (like default values) on numerous projects and never had an issue with it.
I'm really not sure what the question is, as I said in the comments. I'm going to ignore the OWIN stuff since I don't know, frankly.
Firstly, try not to store state at all. Design to pass state back and forth between server and client in models, or the URL, even in the HTML on the client such as in the URLs in the <a> tags your rendering, or (rarely) in cookies, rather than keep things in memory. Stateless designs are way more scalable.
Storing state isn't "usually" done in the Global.asax but then what's usual? I store state as and when I need it, load it or otherwise come by that data. For me in MVC, that's usually downstream of a Controller action, maybe while logging someone in, or reading some data received in a model, like a customer clicking 'add to cart'.
Application state I rarely use, though I store long-lived and shared data within normal fields and properties in long-lived static classes. These die when the app is recycled, but I don't usually care since the apps are designed to work without it, stateless; its usually cached bits of data.
Also, Session_Start only fires when a new browser/agent hits the site. You don't know the user at that point.
The methods in the Global.asax were not specifically designed for 'bootstrapping' state-loading, they're just convenient events for doing whatever you want with. You don't have to use them at all, mine usually just contain logging so I know when sessions start etc.!
I don't know if this helps.
Once you have a plan, come back and ask a targeted question about the OWIN stuff.
"serialization exception thrown in System.Web.Profile.DefaultProfile"
I'm using a lot of custom classes but have marked them all with serializable attribute. The website loads properly initially on the default page, but once a redirection happens to a different page, which inherits the custom "BasePage" class, instead of the default Page class, this exception is thrown :
Unable to serialize the session state. In 'StateServer' and 'SQLServer' mode, ASP.NET will serialize the session state objects, and as a result non-serializable objects or MarshalByRef objects are not permitted. The same restriction applies if similar serialization is done by the custom session state store in 'Custom' mode.
one of the statements in the intellitrace says something like, "failed to serialize System.Web.Profile.DefaultProfile could not be serialized". Isn't it an inbuilt .NET object, and if so cannot I presume that it should be serializable in all cases???
I just ran into this same problem yesterday. The custom object isn't necessarily the problem, but objects inside of that. If you have things like System.Drawing.Image or Dictionary<> or anything else that isn't inherently serializable, its gonna blow up. So you're gonna have to do some digging. I had to do things like convert a List into a string[] to pass it to the web service (which receives a List but shows in intellisense as receiving a string[]).
So I'd rethink that. We also found out that once we got that working in the test server, we weren't done. As soon as we published the web service, other problems started popping up that were similar. Images were not serializable so we converted them to byte[] before sending them, Dictionaries were also not serializable.
I realize this isn't much of an answer, but hopefully of some help.
It is built into ASP.Net, but that doesn't mean it's serializable. There's lots of framework classes that are not serializable.
But also, the Default profile is made to work with the asp.net profile mechanism. Why are you attempting to store that in session? It already has it's own configurable storage mechanism. I think this may be a case where you're in a place where you're fighting the system.
For my particular case, I worked around the problem by creating a new custom class with a Serializable attribute, with a property that would return the HttpContext.Current.Profile object. And then whenever I needed to add the profile into session, I'm adding it through the property of this newly created class. Thanks to #swannee and #Sinaesthetic for their ideas.
maybe the question is wrong but here is what i want to achieve maybe there is other way to do that.
I have ASP.NET application running .net 3.5, there is a client list and few others List based objects that are shared among all users of application. ie. when client logged in his userID and few other properties are saved within some List in Application state. Problem is that this application is heavy and it's application pool needs to be restarted once a day or so so all the information saved in these List objects is lost. While client personal data which is saved in Out-of-Proc mode on external server is saved.
Is there any way to workaround it ? Shared Session? Something like that.
PLEASE NO MSSQL SOLUTIONS...
Cheers, pros !!!!
Have you looked at caching the lists of data?
This SO article has some good detials.
You should only use Application State as a cache for data persisted elsewhere. You would then use Application_Start or some Lazy loading wrapper class to retrieve such persisted data into the application object.
If you are storing volatile data not persisted elsewhere in the application object then you are in trouble. Hopefully you would have abstracted access to the application object behind some wrapper object so that all your code is accessing the wrapper not tha application object. Now you would need to ensure the modifications are saved elsewhere so that they can be recovered on restart.
To be frank the Application state object is really an aid in porting ASP-Classic sites. Since you should really just treat the application state as a cache, there is an overlap in functionality between it and the ASP.NET Cache object.