Update a column when closing a window in asp.net - asp.net

I have a table of records that has a column processed. In my web page i'm using sessions.. because every user that opens the page should see different data from the table.. so i initially have processed=0 and when i'm selecting my data i'm updating the column where processed=0 and then i'm updating the column to processed=2 so that way if another opens the page he gets other data... but the problem is that if the user closes the page without changing anything about the page i need to put my column back to 0 processed=0 but i can't handle an event on the close button of the page... and also not on the log out because they may close the page without logging out... so does anyone has any idea how can i manage this?
note that i'm using asp.net with vb.net

for what you need, don't rely on some browser action, i.e. browser close button (what if internet goes down for one of the users :) ).
The simple way to achieve this is to perform somekind of polling at both levels, i.e. in the db(since your flag is stored in the db) and at the code. Polling implies, constantly making request for certain operation after a fixed interval of time. Obviously, polling is taxing, but it is one of the solution.
Another way to do is to as soon as your user Logs in, you create a Http Long lived request, which neither of the parties(client and server) break and as soon as it ends, you set the flag to 0 again, but having a parallel long lasting request along with all those others is not simple. It is termed as Comet
So I would recommend, to constantly make an ajax request say every 2minutes, to update a certain field, say LastActive in user accounts table. This would constitute your Code side Polling
and Then create a sql server job, which constantly monitors this LastActive field and say, if the difference between it and current DateTime is more than 2.10 minutes, it sets the processed=0 for that user.
You can also look into SessionExpire fields(or whatever it is called), if you are using Forms Authentication of ASP.NET through Session

Related

I have multiple users, can i lock the web page so that only one user at a time can update a record?

Can anyone help or provide me with some suggestions for the below query.
I have a web form (Minutes of Meeting) and 8 users that need to access this web page and update their area. A user may have more than one area to update and essentially i would like to some how lock down the web page if possible when a user is using it so that no other user can update this web page till joe bloggs has finished with it.
I have a Active Directory security group set up to restrict the site to that group of users only, but i need to think of a solution to the above?
Is there a way i can do this via a web control or via SQL?
There must be better ways to do it. However, Is it possible for you to introduce a sql table column similar to "UpdateInProgress" (bit). Any update process sees that column, If 0 then It updates to 1 and after It saves the changes and updates back to 0 so that the form is available for other to update. If update process sees 1, It can't update the web form because update is in progress.
I also suggest to introduce another column named "UpdateInProgressBy" to check who has opened it for editing.
First of all we must note that there is a big time from the moment the user reads the data, get it in a page, change them and then try to write them back. So we are not talking for the lock command on SQL, nether any other lock that happens in milliseconds and help to synchronize threads, but here we must synchronize people and what they write.
There is also a problem if the user leave the page for any reason and this can make the data lock for ever.
This problem can solve with two approaches.
the easy one, when a user try to save data you must check if the same data have been change in the middle, and warn him, or show a merge dialog, or merge programmaticall, or something similar - I do not know what you won.
the difficult way is to constantly monitor the page that read and change the data, and keep this monitor results on a common table in the data base, and there if a user have been and stay on page, the rest users get a warning and read only data, until the user go.
This monitor must be made with javasript and must know even if a user abandon the page.
SET TRANSACTION ISOLATION LEVEL as SERIALIZABLE
for more information check this link:
http://msdn.microsoft.com/en-us/library/ms173763.aspx

session object design pattern

I'm looking to build an ajax page; it's a reporting page. By default, load today's report. On the page there's a calendar control and when the user clicks on a date, reload the gridview with the corresponding data. Is it considered good practice to do the following:
1) on the first page load, query the data for the page
2) put the query result in the session object and display it in a gridview
3) if the user requests new data, get new data from the query with different parameters
4) put the result of the second query in the session object and display it
5) if the user then requests the data from the first query, get it from the session object
6) do the sorting and paging with the data held in the session.
Note: the data of each query will contain about 300-500 rows and about 15 columns. I'd like to do all this with ajax calls. What are some suggestions and pitfalls to avoid.
Thanks.
I would use Backbone.js:
Server produces report in JSON format.
Client has a Backbone.js Model for this report, which binds to the JSON endpoint.
Client renders the Report Model as a Backbone view.
Client reloads the report from server only when appropriate.
Reports from previously viewed days will still be around in the client as Backbone Model instances, so you don't need to reload from server unless the user forces. I believe this is your main concern?
You're probably still in the realm of can-do-without-a-client-side-framework, but if you plan on doing more of these pages or getting any more complex, you can go to spaghetti pretty quickly without something like Backbone.js.
PS. I just noticed this is .NET related. I know nothing about .NET so maybe there's a built-in client-side framework that can do something similar.
EDIT (updated after reading comment):
For server-side caching, I think a either a denormalized report table in the DB or a separate dedicated cache store (e.g. memcache) is a better practice than session object.
It depends though. If there was say, 1 possible report per-user per-day, and you didn't have memcache set up, and you don't want to use the DB for whatever reason, then it could make sense to store it in their session object. However, if each day's report is the same for all users, you're now caching it N times instead of 1. It could also be hard to invalidate from an external hook and the user loses their cache when they logout.
So I would probably just have a typical get-or-set pattern to try and load report from cache first, and fallback to DB. Then invalidate/update the cached report only when the user forces, or if data used to create the report has changed. AJAX call requests the report by date or however a report is identified.
Since you are hoping to use the data in Javascript Ajax scenerios it would make the most sense to create a HTTP Handler to query and return the needed data result sets on demand.
Using the session object is not a solution because it cannot be accessed asynchronously. As a result, your page would not be able to query this data to feed back to your Javascript objects (unless you created an HTTP Handler to send it back, but that would be pointless when you could just query the data in the HTTP Handler directly).
You are forgetting about windows. A client isn't a window, a client is a browser it can contain many windows/tabs. You need to make sure you are rendering/feeding the correct window. Usually i handle this by submit hidden values.
Problem is separating resuming a session / Starting a new window.
I wouldn't bother holding more than one copy of the query in the Session. The primary reason you'd want to hold it in Session is to improve the sorting/paging speed, presumably. Users expect those to be relatively fast, but choosing new dates can be slower. Plus, what's the likelihood that they'll really reload the first query?
The other answers raise good pitfalls with storing in Session in general.

very large viewstate breaking web app

I have a web app, that consumes a web service. The main page runs a search - by passing parameters to a particular web service method, and I bind the results to a gridview.
I have implemented sorting and paging on the grid. By putting the datatable that the grid is bound to in the viewstate and then reading / sorting / filtering it as necessary - and rebinding to the grid.
As the amount of data coming back from the web service has increased dramatically, when I try to page/sort etc I receive the following errors.
The connection was reset
The connection to the server was reset while the page was loading.
I have searched around a bit, and it seems that a very large viewstate is to blame for this.
But surely the only other option is to
Limit the results
Stick the datatable in the session rather than the viewstate
Something else I am unaware of
Previously I did have the datatable in the session, as some of this data needed to persist from page to page - (not being posted however so viewstate was not an option). As the amount of data rose and the necessity to persist it was removed, I used the viewstate instead. Thinking this was a better option than the session because of the amount of data the session would have to hold and the number of users using the app.
It appears maybe not.
I thought that when the viewstate got very big, that .net split it over more than one hidden viewstate field, but it seems all I'm getting is one mammoth viewstate that I have trouble viewing in the source.
Can anyone enlighten me as to how to avoid the error I'm getting? If it is indeed to do with the amount of data in the viewstate?
It sounds like your caching the whole dataset for all pages even though you are only presenting one page of that data. I would change your pagination to only require the data for the current page the user is on.
If the query is heavy and you don't want to have to be constantly calling it over and over because there is a lot of paging back and forth (you should test typical useage pattern) then I would implement some type of caching on the web service end to cache page by page (by specific user if the data is specific to a user) and have it expire rather quick (eg a few minuites).
I think you need to limit the total amount of data your dealing with. Change your code to not pass back extra data that might never be needed is a good place to start.
EDIT: Based on your comments:
You can't change the web service
The user can manipulate the query by filtering or sorting
There is a large amount of data returned by the web service
The data is user specific
Well I think you have a perfect case for using the Session then. This can be taxing the the server with large amounts of users and data so you might want to implement some logic to clear the data from the Session and not wait for it to expire (like on certain landing pages you know the user will go when they are done, clear the session data).
You really want to get it out of the ViewState beacuse it is a huge bandwidth hog. Just look at your physical page size and that data is being passed back and forth with every action. Moving it to the Session would eliminate that bandwidth useage and allow for you to do everything you need.
You could also look at the data the web service is bringing back and store it in a custom object that you make as 'thin' as possible. If your storing a DataSet or a DataTable in your Session, those objects have some extra overhead you probably don't need so store the data as an array of some custom thin object and just bind to that. You would need to map the result from the WS to your custom object but this is a good option you cut down on memory useage.
Let me know if there is something else I am missing.
I wouldn't put the data in either the view state or the session. Instead store the bare minimum information to re-request the dataset from the web service and store that (in either view state or session, or even on the URL). Then call the web service using that data and reaction the data on each request. If necessary, look to use some form of caching (memCache) to improve performance.

Can I stagger UpdatePanel updates in .NET?

I have a situation in which I select an account and I want to bring back its details. This is a single UpdatePanel round trip and its quite quick.
In addition, I need to bring back some transactional information which is from a much bigger table and takes a couple of seconds for the query to come back.
Ideally, I would like to put this into a second update panel and update this additional information once it has been received, but after the first update panel has updated i.e. the user sees:
Change account
See account details (almost instant)
See transactional info (2 seconds later)
The only way I can think of doing this is to use javascript to cause a SECOND postback once the account details have been retrieved to get the transaction information. Is there a better way?
You cannot run two asynchronous postbacks using UpdatePanels at once.
(Otherwise, the ViewState would get messed up)
However, you can make two "raw" AJAX requests (without UpdatePanels) at once, if you're willing to process the results yourself.

Best way to keep track of current online users

I have a requirement that my site always display the number of users currently online. For example, "35741 Users Currently Online". This is not based on a log in, simply how many users are currently on my site. I have tried using Session Start/Session End for this, however session end is not reliable. Therefore I get inflated numbers, as my session start adds numbers but session end doesn't remove them because it doesn't fire.
There is no additional information to be gathered from this (reporting, etc), it's simply requested that the number show up. Very simple request that's turning into a huge deal. Any help is appreciated.
EDIT:
I should specify that I have also tried using a database for this. Simple table that contains a session ID and a last activity column. With each page hit, I check to see if the session is in my database. If not, insert. If so, update with activity time. Then I run a procedure that sweeps the database looking for sessions with no activity in the last 20 minutes. This approach seemed to kill my SQL server and/or IIS. Had to restart the site.
Best way is like you do, but time it out via activity. If a given session doesn't access a page within 5 minutes or so, you may consider them no longer active.
If you're using ASP.Net membership, take a look at GetNumberOfUsersOnline.
For every user action that you can record, you need to consider them "online" for a certain window of time. Depending on the site, you may set that to 5 minutes. The actual web request should take less than a second. You have to make some assumption about how long they might stay on that page and do nothing but be considered online.
This approach requires that you keep track of the time of each users last activity.
Use Performance Counters:
State Server Sessions Active: The
number of active user sessions.
Expanding what silky said in his answer - since really http is stateless to determine if the user is currently 'online' you can really only track how long since the user last accessed your site and make a determination on how long between requests your consider to still be active.
Since you stated that this isn't based upon users logging in may it's a simple of how many different IP addresses you received requests from in the past 5 minutes (or however long you consider the 'online' timeout to be).
Don't use sessions for this unless you also need sessions for something else; it's overkill otherwise.
Assuming a single-server installation, do something like this:
For each user, issue a cookie that contains a unique ID
Maintain a static table of unique IDs and their last access time
In an HttpModule (or Global.asax), enter new users into the table and update their access times (use appropriate locking to prevent race conditions)
Periodically, either from a background thread or in-line with a user request, remove entries from the table that haven't made a request within the last N minutes. You might also want to support an explicit "log out" feature.
Report the number of people online as the size of the table
If you do use sessions, you can use the Session ID as the unique identifier. However, keep in mind that Session IDs aren't issued until you store something in the Session dictionary, unless you have a Session_Start() event configured.
In a load balanced or web garden scenario, it gets a little more complicated, but you can use the same basic idea, just persisting the info in a database instead of in memory.
When the user logs in write his user name into the HttpContext.Current.Cache with a sliding expiration (say 20 minutes).
Then in the Global.asax.cs in the Application_PreRequestHandlerExecute "touch" the cache entry for the current users so it resets the sliding expiration.
When a user explicitly logs out, remove his username from HttpContext.Current.Cache.
If you do this, at any given time HttpContext.Current.Cache.Count will give you the # of current users.
Note: this is assuming you aren't using the Cache for other purposes.

Resources