How do i lock an asp.net page from multi-user editing? - c#

i have a page with a series of checkboxes that authenticated users can change. I need to make this page only editable by one person at a time. So if a user goes into it and edits one of the checkboxes, noone else can go into the page and change other checkboxes.
I thought about an edit page link and a readonly page link (all controls disabled), then set a database flag if user enters under edit mode, but my concern is i wouldn't know if the user changed something, then just x'd out of the browser/app, locking everyone else out.
This is an internal app to company. Has anybody done something like this?
Any ideas or thoughts or suggestions?
Thanks

We have this functionality on an older ASP app. The user will load data with some type of primary key. We put in a DB entry to "lock" that page. If they correctly move through the site, it will unlock the resources at that time.
Other users opening this page will receive indication that the page is locked and a read-only version is rendered.
It would be fairly trivial to code a unPageUnload AJAX call to reset the lock for browser closing. We don't find this to be much of an issue and old locks are just cleared by an evening process if more than 4 hours old.
Our situation is where the pages are tied to specific regions of data. If this is a general config screen, I think a more dynamic AJAX solution that pushed the updates back and pings for changes might make sense. You would have to decide if you want to disable changes from others after the first update is received or implement collision detection for the data.
Some type of hashing of the page data would probably make this easier to detect changes.

You do what you said, but add a client side timer which will ping the server and tell you they are still there. If you don't get a ping within x mins you could let a new user go into edit mode but perhaps warn them (or not).

What about letting all users edit this page and how your script check in for page updates? Just like SO does, while you are typing in an answer, an orange message appears above saying "At least one new answer has been posted". You could display something like "The page has been modified since you last opened it".
There was something like timer in ASP.NET AJAX. You could use that to talk to the server to send "IN EDIT" status updates. You can even go further. Say you send "LOCKOUT REQUEST" requests every 15 seconds asynchronously and you expect to receive the "LOCKOUT GRANTED" response from server. If the response hasn't been received, you disable all controls on the page until maybe the next request receives the confirmation (the previous message could have been lost in the network). This way, if one user closes the browser, the other won't have to wait many minutes or hours until they get the edit permission.
Essentially, you need a distributed implementation for a critical section concept. It maube a challenge to implement it over HTTP. But that's a very interesting challenge, isn't it?

If you're trying to prevent two users from updating a db record and over-writing each other, perhaps it would be easier to detect this than prevent it.
On strategy for this is to include a "version" field in the record, and save that in a hidden field when rendering the page.
Then you simply include that as a condition of your update (i.e. UPDATE ... WHERE ID = myID AND VERSION = myversion) - if your update returns 0 rows, you know that someone else modified the data, and you can then decide what to do - reload the new data, offer the user a chance to compare them, etc.

How about an alternative to an extended lock?
Since you appear to be manipulating relatively small amounts of data, it would be more polite to put an encoded version of original state of the data in a hidden form field (or a datestamp, though that's less reliable; a hash of the values would work for larger amounts of data). In a transaction, check the state of the database against the hidden form values; if the original record has changed since the user submitted the changes, you reject the update. If not, accept the update, and commit the transacation.

Another approach could be to have an Application variable that contained a map or dictionary of locked items.
So, when one user hits edit, add an entry to the AppVariable Map or Dictionary, with the Key set to the primary ID of the field being edited. Then for all further requests, when they change between records, do a check of the ID within the map and if its being edited, Toggle off any update buttons. If you want to do it AJAXy, add a timer and an UpdatePanel and poll to see when the lock is released, then refresh the page with the updated data and enable the update buttons again.
Or, as a slightly greater UI, allow the users to edit while waiting for the lock to release ( the Map item to be removed ), then when it is removed, compare the fields they have been working on, with the updated database values and allow them to overwrite/merge their changes.
The only real downside is, 1) You would need to create one Application level Dictionary or Map for each table that you want to lock/unlock. 2) If you get into a webfarm environment, it breaks and you would have to use a different system.
Does that make sense?

Related

Prevent state change updates

I am using Entity Framework in a Blazor server side project, and I have a page where a user can edit data. I have a Cancel button on the edit page that updates the Entity Framework context object to cancel pending changes in it, and then redirects to another page. When the user hits Cancel, you can see values change back to their original values on the page before the redirect happens. So there is unnecessary client updating happening here which is causing extra network traffic. Is there a way to tell Blazor to not go through the state change process so I can prevent this?
It would be nice if you could show some code and make a Minimal, Reproducible Example, but since you didn't, I will give you a theoretical answer.
What you could do is have a "dummy" class for holding the values on the user client and have a class that will be manipulated by the server side, so you can manipulate when the data in the client side should change or not.
When the user edit the data, it will edit the dummy class and then map the values to the correct class, but when the user clicks on cancel, that won't be there.

How to do Database changes after user exit from the website?

i have a rental website and when someone wants to make an offer he has 7 min to pay, if he wont pay the offer will delete.
i have a timer on my form to check the time, and when the timer is on 0:00 and the user didn't pay his offer will delete.
MY question is how can i check if user log out? i mean user can exit from the site (by clicking X) and his session will end.
i want to delete his rent offer if user quit from the website.
Thanks for the helpers.
For this scenario, I don't think its a good idea to rely on browser events, such as onunload & onbeforeunload. User may have opened more than one tabs. So closing one tab will remove the offer. Furthermore, if the user click back button these events will be fired. So don't rely on browser events for this.
(But, if the user clicked on LogOut then you have enough information to delete the offer.)
Perhaps you can use following approach to handle your original problem:
When user create a new offer store these details in the database with two extra columns: OfferCreatedUtcDateTime and PaymentCompleted(which should be false).
If the user completed payment successfully, you can set PaymentCompleted to true.
Then you can use one of the following two options:
Option 1:
Create a windows service which will check above database columns. If the PaymentCompleted == false and OfferCreatedUtcDateTime + offer valid period > CurrentUtcDateTime then you can delete this offer.
Option 2:
As mentioned by #nvoigt in the answer, every time user search for a resource you can ignore or delete offers which satisfies the condition mentioned in Option 1.
Hope this helps.
First do not fulfill offers that are older than your timeout(7mins) I'm assuming that you have OfferCreatedDate timeStamp. Second create a job that will clean all unfulfilled and expired offers. Hope this helps
You cannot. Not reliably. The user will not send you a nice message when he does not do something.
You can program your site to send you a signal if something happens, but you need to know when something doesn't happen. And it can "not happen" in multiple ways, many of them not allowing a signal to be transmitted.
Just imagine your user's train goes into a tunnel or he kills his browser, his computer crashes or cell phone loses battery power. All events that happen daily and all of them will not notify you nicely. They cannot.
So what you need to do is figure out a way to delete all obsolete orders. Either on a timer in an independent service, or maybe before a user places any order. But you need do that in a place independent of the user playing nice with your frontend app.
One way of handling this would be to save the date and time of creation with every offer you give out. Every time you check available resources and create a new offer for a user, delete all offers that are older than your limit before giving out new offers, thereby freeing up the blocked resources.
What about not focusing on how to set the timer to 0 when user session end but check other users timer's when another user create one ?
Then you can still have the checking process for the connected user, when it goes to 0 it stopped but for the case the user close the windows or leave, when another user create a reservation you also and firstly check if there's timer still alive older than 7 minutes and you release them so the user currently doing a reservation can do this one that has just been set as available ?

Clear IE cache C#

I have a problem with Internet Explorer and cache (I think).
Easy explained, I'm trying to edit a user in my SQL database using LINQ-to-SQL, which works perfectly.
After the user is edited, it sends me back to a page I've made with a list of all users, and I can then click on any user I want to edit.
The problem is, if I then click on the same user I just edited, the changes haven't been done, but in the database, they have been changed, so I think there might be a problem with the IE cache or something.
Anyone knows if there is a way in Visual Studio to clear the IE cache for this specific page?
I know I can just press ctrl+F5, but I want it to update without having to press ctrl+F5.
Btw, my website is programmed in c# and .net 4.0.
You probably need to refresh your data context.
L2S doesn't 'cache', as such, but it sometimes needs prompting to refresh the data from the database, depending on how you've done your data update.
You can try appending random number in the link of the user, like:
<a href="Page.aspx?userId=123&rnd={JUST A RANDOM NUMBER OR TICKS} />
This concept is the same as the JavaScript being cached, in the IIS it will have the same interpretation but will force to get the new one.

fighting spam bots

I have C# form in the site and want to prevent spam bots from filling it. The trick is, that I want to avoid CAPTHA or any other user input to avoid loosing a single registration.
Here are some techniques I have in my mind:
Hidden input field (question: is this still effective?)
Track time, since the first user input (focus on FirstName) till posting a form.. Humans will take more than 3 seconds to complete a form (even with auto-fill), where bots take a second or less to fill in registration and post it. (question: if I start timer with the first user input, when should I stop it?)
Put in the form tag a fake post url, or post form to itself, and only on Submit button click action to add a real post url with javascript. (question: wonder if new spam bots can cheat this?)
I would be glad to hear other techniques I could adopt, again, without using CAPTCHA, spam filters, form verifications and even validation. Thank you
would be good to have some sort of flash which asks you to reconnect dots (so that it is interactive and doesnt require typing), and when the user does it correctly, you can post with submit to check.
Never liked CAPTCHA, especially the wierd ones where even humans have problem intepreting it :)
A year ago there was a nice control for asp.net that put a hidden field on the form. With a javascript formula. Robots posted it back - and it wanted the result (stored the result first in the session). basically, as robots dont interpret the form in a browser (too slow).... ;) Most got just thrown out there.
Also, another tip: put in hidden fields for the email to address. Some (old)php forms use a mailer supportnig this. OBVIOUSLY only a robot fills that out ;) If not empty -> garbage.
Anyone else have any smart ideas? ;)
I would say stick with Captcha or a similar thing where the user has to type something in.
The problem with using JavaScript is that not everyone has javascript turned on and quite a few have it turned off for various reasons.
Now if you want to really track time, send a hidden form field with the server time filled in. When the postback occurs take the delta of that with the current time. Obviously if the field is missing then you know someone directly posted.

Controlling browser forward/back functions in web application

I'm writing a web-based application for internal use within the business where I work. It's a fairly complex application, with a lot of forms that will allow the user to view and enter data, which once saved will be stored in a database.
One thing I'm anxious to avoid is allowing a situation to exist where a user might enter large amounts of data in the browser, and then (either deliberately or inadvertently) navigate off the page without saving the changes. To this end, I have already implemented an entry page which opens up a new browser window in which there are no navigation controls at all; only what is provided on the web pages themselves.
However, there are two potential ways in which a user could still lose data:
The browser Close button is still enabled, and a user could potentially lose work by clicking it inadvertently. I can probably live with this, as it falls at the extreme end of helping the user not to shoot himself in the foot.
In Internet Explorer (and, apparently, in Firefox) the Backspace button works like a Back button. I only discovered this accidentally, and have as yet been unable to find a simple way of stopping this behaviour. This is potentially a problem, as an inadvertent use of the Delete key (e.g. having positioned the cursor in a read-only textbox, or when the cursor isn't on any particular field in the page) will navigate off the page.
What I would like to do, as a minimum, is prevent Backspace from navigating off a page if that page has any user-writable fields on it and any of those fields have been changed by the user since the form was loaded. Ideally, I would like to disable this particular use of the Backspace key completely, while the user is logged into this web application. The two possible ways that I can think of, for achieving this, are: (1) clear the browser's history as each page is loaded, or (2) trap the Backspace key and only allow it to work if the cursor is positioned within a field whose text can be changed (e.g. a textbox).
Can anyone suggest how I could achieve either of these things? The solution needs to be programmatic, rather than something that has to be manually configured on every browser in the company.
Instead of blocking* functionality that your users have learned to expect in their daily activities at work and at home, why not work with it? Make the "back" button actually take them to the previous screen as expected, and use AJAX to silently save the form as they fill it out (say, every 5 or 10 seconds), so when they return to the form you can check to see if they already have partial, unsubmitted values saved and reload them.
This approach aligns with the realities of web-based applications and delights users if implemented well. An alert that says "you did something wrong" just frustrates users and makes them trust your application less. Remember - users almost never do the wrong thing. It's our applications that aren't aligned with usage.
* more like trying to block functionality. As you've discovered, people who designed the interwebs and web browsers never really intended for site developers to totally disable moving back and forward in the navigation history.
What about something like this? You can ask them if they are sure before they leave.
var changes = false;
window.onbeforeunload =
function()
{
if (changes)
{
var message = "Are you sure you want to navigate away from this page?\n\nYou still have unsaved changes.\n\nPress OK to continue or Cancel to stay on the current page.";
if (confirm(message)) return true;
else return false;
}
}
You should look at the Javascript's window.unload event.
This is fired when the use tries to leave the page. You can't totally stop them leaving the page, but you can give them a chance to cancel.
try this
window.onbeforeunload() {
return "Are you sure you want to navigate away?";
}

Categories