views:

62

answers:

3

I'm sure that this question has already been asked, but I don't really see it.

Using asp.net and c#, how does one track the pages that are open/closed?

I have tried all sorts of things, including:

  • modifying the global.asax file application/session start/end operations
  • setting a page's destructor to report back to the application
  • static variables (which persist globally rather than on a session by session basis)
  • javascript window.onload and window.onbeforeunload event handlers

It's been educational, but so far no real solution has emerged.

The reason I want to do this is to prevent multiple users from modifying the same table at the same time. That is, I have a list of links to tables, and when a user clicks to modify a table, i would like to set that link to be locked so that NO USER can then modify that table. If the user closes the table modification page, I have no way to unlock the link to that table.

Thank you for reading and for your help.

+1  A: 

I think your going the wrong way about this...

You really should be handling your concurrency via your business layer / db and not relying on the interface because people can and will find a way around whatever you implement.

I would recommend storing a 'key' in your served up page everytime you serve up a page that can modify the table. The key is like a versioning stamp of the last time the table was updated. Send this key along with your update and validate that they match before doing the update. If they don't then you know someone else came along and modified that table and you should inform the user that there was a concurrency conflict, the data has changed, and do they want to see the new data.

Kelsey
+1  A: 

You should not use page requests to lock database tables. That won't work well for many reasons. Each request creates a new page object, and there are multiple application contexts, which may be on multiple threads/processes, etc. Any of which may drop off the face of the earth at any point in time.

The highest level of tackling this issue is to find out why you need to lock the tables in the first place. One common way to avoid this is to accept all user table modifications and allow the users to resolve their conflicts.

If locking is absolutely necessary, you may do well with a lock table that is modified before and after changes. This table should have a way of expiring locks when users walk away without doing so.

Eg. See http://www.webcheatsheet.com/php/record_locking_in_web_applications.php It's for PHP but the concept is the same.

kervin
+2  A: 

You should not worry about tracking pages open or closed. Once a webpage is rendered by IIS it's as good as "closed".

What you need to do is protect from two users updating your table at the same time by using locks...For example:

    using (Mutex m = new Mutex(false, "Global\\TheNameOfTheMutex")) 
    {
            // If you want to wait for 5 seconds for other page to finish, 
            // you can do m.WaitOne(TimeSpan.FromSeconds(5),false)

            if (!m.WaitOne(TimeSpan.Zero, false))
                Response.Write("Another Page is updating database.");
            else
                UpdateDatabase();                              

    } 

What this above snippet does is, it will not allow any other webpage to call on the UpdateDatabase method while another page is already runing the UpdateDatabase call.So no two pages can call updatedatabase at the same exact time.

But this does not protect the second user from running UpdateDatabase AFTER the first call has finished, so you need to make sure your UpdateDatabase method has proper checks in place ie. it does not allow stale data to be updated.

ace
+1 (Although locking tables is probable not the best Idea)-- btw it is "m.WaitOne" instead of "m.WatiOne"
dampee
"it's as good as closed" was the answer I was looking for. I'll be sure to try the Mutex solution though
thanks for pointing out the typo, i corrected it to WaitOne.
ace