views:

130

answers:

4

Howdy.

I'm developing a webapp that allows the editing of records. There is a possibility that two users could be working on the same screen at a time and I want to minimise the damage done, if they both click save.

If User1 requests the page and then makes changes to the Address, Telephone and Contact Details, but before he clicks Save, User2 requests the same page.

User1 then clicks save and the whole model is updated using TryUpdateModel(), if User2 simply appends some detail to the Notes field, when he saves, the TryUpdateModel() method will overwrite the new details User1 saved, with the old details.

I've considered storing the original values for all the model's properties in a hidden form field, and then writing a custom TryUpdateModel to only update the properties that have changed, but this feels a little too like the Viewstate we've all been more than happy to leave behind by moving to MVC.

Is there a pattern for dealing with this problem that I'm not aware of?

How would you handle it?

Update: In answer to the comments below, I'm using Entity Framework.

Anthony

A: 

Locking modification of a page while one user is working on it is an option. This is done in some wiki software like dokuwiki. In that case it will usually use some javascript to free the lock after 5-10 minutes of inactivity so others can update it.

Another option might be storing all revisions in a database so when two users submit, both copies are saved and still exist. From there on, all you'd need to do is merge the two.

Joey Robert
A: 

You usually don't handle this. If two users happen to edit a document at the same time and commit their updates, one of them wins and the other looses.

Resources lockout can be done with stateful desktop applications, but with web applications any lockout scheme you try to implement may only minimize the damage but not prevent it.

Don't try to write an absolutely perfect and secure application. It's already good as it is. Just use it, probably the situation won't come up at all.

User
Due to the nature of the application, there will definitely be some situations where this will come up.
littlecharva
+3  A: 

Unless you have any particular requirements for what happens in this case (e.g. lock the record, which of course requires some functionality to undo the lock in the event that the user decides not to make a change) I'd suggest the normal approach is an optimistic lock:

Each update you perform should check that the record hasn't changed in the meantime.

So:

  1. Put an integer "version" property or a guid / rowversion on the record.
  2. Ensure this is contained in a hidden field in the html and is therefore returned with any submit;
  3. When you perform the update, ensure that the (database) record's version/guid/rowversion still matches the value that was in the hidden field [and add 1 to the "version" integer when you do the update if you've decided to go with that manual approach.]

A similar approach is obviously to use a date/time stamp on the record, but don't do that because, to within the accuracy of your system clock, it's flawed.

[I suggest you'll find fuller explanations of the whole approach elsewhere. Certainly if you were to google for information on NHibernate's Version functionality...]

mwardm
A: 

If you use LINQ to SQL as your ORM it can handle the issues around changed values using the conflicts collection. However, essentially I'd agree with Mastermind's comment.

Coolcoder