I have an application variable which is populated onstart (in this case it is an array). Ideally I need to rebuild this array every 3 hours, what is the best way of going about this?
Thanks, R.
Save the time you last refreshed the variable contents.
On every request, check the current time against the saved time. If there's a three hour difference, lock and refresh the variable.
As long as there are no requests, the variable also needs no refreshing.
If your application variable must remain "in process" with the rest of the site's code, the way suggested by Tomalak may be your only way of achieving this.
However, if it's possible that the application variable could effectively reside "out of process" of the website's ASP code (although still accessible by it), you may be able to utilise a different (and perhaps slightly better) approach.
Please see "ASP 101: Getting Scripts to Run on a Schedule" for the details.
Tomalak's method is effectively Method 1 in the article, whilst Method's 2 & 3 offer different ways of achieving what is effectively something happening on a schedule, and avoid the potentially redundant checking with every HTTP request.
Related
In my experience it is not unusual for a web app to be open in more than one tab in the same browser instance. It may be that the user wants to look at two parts of the database side by side or perhaps there are two different apps in the same domain.
Now in my naivety I had assumed that two instances of the same app would have their own set session variables so instance A could have Session(“user”) = “John” and instance B could have Session(“user”) = “Sally”. But I’ve discovered to my horror that this isn’t always true, and usually isn’t. My testing shows that if in web.config SessionState section cookieless=true/UseUri then the two instances have their own set of Session variables. But if cookieless=false/UseCookies then they share one set. Of course cookieless=true is not a good idea and AutoDetect/UseDeviceProfile are almost always going to be the same as false.
So if instance A does Session(“user”) = “John” then instance B does Session(“user”) = “Sally”, instance A now sees Session(“user”) = “Sally”.
This is so patently awful that I feel I must be missing something so can anyone put me right?
If that’s the way it has to be, what are the alternatives? Use ViewState? But another horrible thought, I’m saving ViewState in SessionState.
An example and further thoughts
Imagine you have an ASP.net web page that lets the user look up a customer in a list then view its details. The code stores the customer no. in Session(“custno”) and uses that as the key in an SQLDataSource. You could argue that this is poor programming technique but I’m using it simply as an example to illustrate what can happen.
The user sits in front of his computer and looks up customer 1234. The code duly does Session(“custno”) = 1234. Before he has finished working on 1234 the user needs to look up customer 5678. So he opens the page in another window, selects 5678 and the code now does Session(“custno”) = 5678. Having finished with 5678 he goes back to 1234, changes something vital, saves the change and to his horror finds he has updated 5678. Surely in a well organised society this should not happen.
Session variables are often recommended as a good way to pass variables between pages with the implication that a ‘session’ is one client sat in front of one computer using one app. And it can do exactly that if SessionState is set to cookieless=true but not if cookieless=false (and we don’t really want to use cookieless=true).
I was hoping that someone would say “just do this and it will work the way you expect” but it seems I’ve been mistaken all along and I suspect many others have been too.
So what to do about it? A comment offers several solutions for which I say thank you however none seem to me to be particularly satisfactory.
Creating a different ID for each window and making it part of the URL looks very much like cookieless=true and with the same disadvantages.
Forcing a new session to be created for each browser window. I’d be interested to know how this is done because New Session for New window in ASP.NET suggests it is not possible (though it does demonstrate that someone has been this way before).
“Storing anything you need in the window itself” is I guess synonymous with using ViewState instead of the session. I can see that could work except I store ViewState in the session to reduce transmitted page size! And anyway ViewState has a number of disadvantages including not being available until well in to the page life cycle.
Creating a page id and saving it in ViewState as described by asp.net - session - multiple browser tabs - different sessions? at first looked promising but I fear it is not going to work well with a PageStatePersister. More experimentation needed.
On a new website, I've an huge formular(meaning really big, needs at least 15-20min to finish it), that configure the whole website for one client for the next year.
It's distributed between several tabs(it's a wizard). Every time we go to the next tab, it makes a regular(non ajax) call to the server that generate the next "page". The previous informations are stored in the session(an object with a custom binder).
Everything was working fine until we test it today with all real data. Real data needs reflexion, work to find correct elements, ... And it takes times.
The problem we got is that the View receive a Model partialy empty. The session duration is set to 1440 minutes(and in IIS too). For now what I know is that I get a NullException the first time I try to access the Model into my view.
I'm checking the controller since something like 1 hour, but it's just impossible it gives a null model. If I put all those data very fast, I don't have any problem(but it's random data).
For now I did only manage to reproduce this problem on the IIS server, and I'm checking elmah logs to debug it, so it's not so easy to reproduce it.
Have you just any idea about how should I debug this? I'm a little lost here
I think you should assume session does not offer reliable persistence. I am not sure about details but I guess it will start freeing some elements when it exceeds its memory limit.
You will be safer if you use database to store that information or you could introduce your own implementation for persisting state.
in addition to ans provided by #Ufuk
you can easily send an ajax request every 1 minute which would actually do nothing but by doing this the session wont get expired and site will continue to run in extended periods
The problem was that the sessions wasn't having enough space I think. I resolved temporary my problem by restarting the application pool. Still searching a solution that will not implies to changes all this code. Maybe with other mode of session states, but I need to make my models serializable.
Here's my issue, we have a large patient object that is used on multiple screens throughout the admin. Each screen contains different information about the same patient. It can't all be on one screen.
The only time I want to persist the patient is when the user clicks save. I need to have an in memory patient somewhere. A user may be in the admin, change patient information on various screens, run validation and decide to not save that patient. This is typical use.
Is it ok to store this patient in the session? Or, is there a better approach to do this? At most this admin would have 20 users with access.
Opinions may vary on this. Session is tricky, especially if you use something other than in-memory session. Distributed session will break a non-serializable object. If this object is a simple POCO or object you control, try your best to make it play with serialization. If it does you're set. For an admin tool without much load I'd say you'd be fine.
Hey I found this - know nothing about the site, but illustrates my point:
https://www.fortify.com/vulncat/en/vulncat/dotnet/asp_dotnet_bad_practices_non_serializable_object_stored_in_session.html
I had a similar situation with similar amount of users. I did it and it worked great.
My situation was about scheduling events.
Someone would create an event and through multiple web pages would modify and configure this event. When they were all done it would save all the details to SQL. In the end, I was surprised just how well it worked.
Session should be fine here. You have what appears to be a light user load... but you might want to check exactly how much memory the object takes up, multiply that by the maximum number of users, and see where you are.
If you want to avoid the session altogether, you could use System.Web.Caching to store the object instead, and key the stored object using the users identifier plus some constant string.
In either case, you'll want to be aware of how many web servers are running the application. If it's just one web server, no worries. If you have multiple web servers, you'll want to make sure they are "sticky" - then the user is guaranteed to have all requests processed by the same server. How this is done is entirely dependent on your flavor of load balancing... normally the "IT folks" handle this for you.
Given the chart here, what should I be looking at to identify the bottleneck? As you can see, requests are averaging nearly 14 seconds under load and the bulk of that time is attributed to the CLR in New Relic's profiling data. In the performance breakdown for a particular page, it attributes the bulk of the time to the WebTransaction/.aspx page.
I see that the database is readed also (the orange) and this is seams that one of all pages have delay the rest of pages because of the lock that session make on the pages.
you can read also :
Replacing ASP.Net's session entirely
My suggestion is totally remove the session calls and if this is not possible, find an other way to save them somewhere in database by your self.
Actually in my pages I have made all three possible options. 1. I call the page with out session. 2 I have made totally custom session that are values connected to the user cookie, and last 3. I have made threads that are run away from the session and they make calculations on background, when they finish I show the results.
In some cases the calculations are done on iframe that call a page without session and there later I show the results.
In the Pro version, you can use Transaction Traces, which help pinpoint exactly where the issue is happening.
ASP.Net session appear perfect for a traditional WebForms app, but they do some things that are a serious problem for a modern AJAX and MVC application.
Specifically there are only 3 ways to access the ASP.Net provider:
Locking read & write (default) - the session is locked from AcquireRequestState firing until ReleaseRequestState fires. If 3 requests occur from the browser at once they'll queue up on the server. This is the only option in MVC 2, but MVC 3 allows...
Non-locking read only - the session isn't locked, but can't be saved to. This appears to be unreliable though, as some reads appear to lock the session again.
Session disabled - any attempt to read or write to the session throws an exception.
However with a modern MVC app I have lots of AJAX events happening at once - I don't want them the queue on the server but I do want them to be able to write to the session.
What I want is a fourth mode: Dirty read, last write wins
I think (happy to be corrected) that the only way to do this is to completely replace ASP.Net's sessions. I can write my own provider, but ASP will still call it with one of the 3 patters it supports. Is there any way to make ASP.Net support optimistic concurrency?
This leaves me replacing all calls to the session with a new class that basically does the same thing, but doesn't lock - which is a pain.
I want to keep as much of the current session stuff as I can (most significantly session IDs in various logs) with the minimum amount of code replacement. Is there any way to do this? Ideally I'd want HttpContext.Current.Session to point to my new class but without ASP.Net locking any requests.
Has anyone already done something like this? It seems odd that with all the AJAXey MVC apps out there this is a new problem with ASP.
First of all I say that MS asp.net have lock in the core of "asp.net processing a page" the session, somewhere in the "webengine4.dll" dll for asp.net 4
And I say that from the view point of MS asp.net act correct and lock the session this way because asp.net can not know what type of information we keep on session so can make a correct "last write wins".
Also correct is lock for the session the full page because that way is gives your a very important synchronizations of your program, that from experience now I say you need it for most of your actions. After I have replace the ms session with mine, on all of my actions I need to make global lock, or else I have problems with double inserts, double actions, etc.
I give an example of the issue that I recognize here. Session data are saved on SessionSateItemCollection that is a list of keys. When session reads or write this collection is do it all of them together. So let see this case.
we have tree variables on session, "VAR1", "VAR2", "VAR3"
Page 1.
getsession (actually get all data and place them on list)
session[VAR1] = "data1";
savesession()
result is VAR1=data1, VAR2=(last data of var2), VAR3=(last data of var3)
Page 2.
getsession (actually get all data and place them on list)
session[VAR2] = "data2";
savesession()
result is VAR1=(last data of var1), VAR2=data2, VAR3=(last data of var3)
Page 3.
getsession (actually get all data and place them on list)
session[VAR3] = "data3";
savesession()
result is VAR1=(last data of var1), VAR2=(last data of var2) VAR3="data3"
Note here that each page have a clone of the data, as he read them from the session medium (eg as they last readed from database)
If we let this 3 pages run with out locking, we do not have actually dirty read, nether "last write wins" - What we have here is "the last write destroy the others", because if you think it again, when VAR1 change, why the VAR2 and VAR3 stay the same ? what if you have change VAR2 somewhere else.
and for that reason we can not let this with out lock as it is.
And now imaging that with 20 variables... totally mess.
Possible solutions
Because of the multithread of asp.net of many pools, the only way to keep the same data across pools, and across computers is to have a common database, or a common to all process program like the asp.net State Service.
I select to have a common database as more easy than create a program for that propose.
Now if we connect a cookie that we make, to the user to the data user of the session, and we control the data using a totally custom database field that we know what we like to lock, what not, how to save or change, or compare and keep the last write wins data, we can make this work, and totally disable the asp.net session that is a generic session keeper made for all needs, but not made to handle special cases like this one.
Can asp.net make this work on the future release, yes he can by making an extra field called dirty, and on the session save data, make a merge of data using the dirty field, or something like that, but can not make this now work as it is - at least from what I have found until now.
Actually SessionStateItem have a dirty flag on properties, but did not make this merge on the end of save data. I will really love if some one else think for a solution to the existing ms asp.net session state keeper, I am write what I have found up to now, but this is not mean that for sure there is no way - I have not found it as it is.
Hope that all helps :)
Custom SessionStateModule
in this answer https://stackoverflow.com/a/3660837/159270 the James after write a custom module says: I still can't believe the custom implementation of ASP.Net Session locks the session for the whole request.