Prevent double-clicking on Button - asp.net-3.5

I keep having an issue with users double-clicking on action buttons on my web application, which is meaning duplicate records are being added into my database, and sometimes the user is being charged twice (as the action is being ran twice).
What is the best way of preventing double clicking in ASP.NET?

I see you're concerned about this in the face of users without javascript enabled. If that's the case, you need to deal with it on the server side. One idea to deal with this would be to implement CSRF tokens throughout your app.
This basically keeps a token in the server side session, and also requires the token to be submitted in the request. Provided youreset this token in the session in a timely manner (and assuming that you're using usual ASP.Net mechanisms to serialize access to the session), the second request will be using an out of date token, and can be ignored.

I think the best solution would be to disable button after clicking using Javascript. Try adding onclick function to it:
<input type="submit" onclick="disable_button(this);" />
<script type="text/javascript>
function disable_button(sender){
sender.disabled = true;
}
</script>
It can also be done using server-side code using server controls. Paste this into your pre-render or page_load event:
yourButton.Attributes.Add("onclick", " this.disabled = true; "+ ClientScript.GetPostBackEventReference(Button1,null)+";");
This will basically disable the Button when ever u click it and then calls the server side code as if the button has been clicked.

Have you tried adding a little JavaScript to the submit button?
e.g.
<input type="button" onClick="formSubmit.disabled=true;">
This way the button is disabled right after the first click and won't take the second click ...

I solved this problem by using a session variable without enabling or disabling the button.
In the Page_Load add :
Session["clicked01"] = "0";
in the btnSave_Click :
if (Session["clicked01"] == "1")
{
return;
}
/// save the record
Session["clicked01"] == "1"

Related

How to stop re submitting a form after clicking back button [duplicate]

This question already has answers here:
Prevent user from seeing previously visited secured page after logout
(7 answers)
Closed 6 years ago.
I have a JSP page with a form where you fill up certain details. On submitting the form i call a servlet which then updates details in a database after that i redirect to a page i display a confirmation message to the user.
The problem i have here is when the user clicks back he goes to the form page again where if he clicks a submit button, it creates a new record in the database.
Consider this similar to a shopping cart example where in this case he would buy the same item twice. But the only problem here is i cannot handle this in backend, i.e. the database can never know a redundant operation is taking place.
I need to handle this from the client side.Bit weird but i have to do it this way.
Basically when the user clicks the back button i don't want him to be able to go to the form page and may be just to some other page.
This is a typical HTML form issue, you can solve it through any one of following methods
1) Server side (page expiration): Since you've mentioned that the page refreshes and goes to the confirmation. You can set no-cache and add a page expiration time as -1 to the page you have that form.
So that when user presses the back button, he will see that the page has expired. He will be forced to load the page freshly. This is the behavior that I see in most banking websites.
Response.Buffer = True
Response.ExpiresAbsolute = Now() - 1
Response.Expires = 0
Response.CacheControl = "no-cache"
2) Using turn Key method: When the form loads, you can generate a random key in session memory and also embed it as a hidden value in the page.
During form submission, check the submitted hidden key against the value in session. If exists, then add the entry to database otherwise you can reload the page with a fresh key for the user (who might have done that unintentionally).
In load balanced or web farms, consider persisting the turn key in Database against the current user.
3) Client Side (Not recommended) : You can restrict the user from using the browser back button by removing the page from the history. (One side effect is that it will remove the entire history for that browser tab/window)
history.pushState(null, null, document.title);
window.addEventListener('popstate', function () {
history.pushState(null, null, document.title);
});
If you need the same support for older browsers where push and pop states are not supported, you can use following snippet.
<script>
function preventBack() {
window.history.forward();
}
setTimeout("preventBack()", 0);
window.onunload = function() {
null
};
</script>
Before redirecting to the JSP page send these headers with the response from the controller so that the page is not stored in cache and the browser will always request a new page from the server.
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0);
So every time you go back to that page a new page will be requested from the server and will be displayed with the cleared input fields.
You could implement a PRG-Pattern (https://en.wikipedia.org/wiki/Post/Redirect/Get) using php.
Basically, after successfully submitting the form you redirect to a confirmation page which informs the user that their submission was successful/accepted/etc. and also set a variable which you can later use to check if said submission has been submitted yet.
When the user tries to reload said page or go back you can check the variable and display either the form again or the confirmation page based on if the submission has been submitted already.
I think following flow is the best:
Client submits data to server
Servlet processes it
It returns HTTP 303 redirect to client
Client redirects to success page
After this flow, refresh, back button will work properly.
For more information read Simple Post-Redirect-Get code example

Call javascript function on AutoHotKet

I have requirement to send information to third party tool and fetch some information from this tool using autohotkey.
but i am facing informaiton into textbox and try to fire button click event .
I have used this code to fill the textbox and fire button click event but not able for fire this because textbox event not fired as mention in below code..
pwb.document.getElementsByTagName("input")["rio-search"].focus()
pwb.document.getElementsByTagName("input")["rio-search"].value := startelemnet
fullvalue :=pwb.document.getElementsByTagName("input")["rio-search"].value
Sleep, 500
pwb.document.getElementsByTagName("input")["rio-search"].value := fullvalue
pwb.document.getElementsByTagName("input")["rio-search"].focus()
wbs.document.parentWindow.showOptions()
wbs.document.parentWindow.execScript("showOptions()")
pwb.document.querySelector("button[type=submit]").Click()
but i am try to call the javascript mehtod on textbox focus in autohotkey but not able to call :
<input type="text" id="rio-search" ng-model="$root.keywords" ng-focus="showOptions()" ng-blur="hideOptions()" class="form-control ng-valid ng-touched ng-dirty ng-valid-parse" placeholder="Search">
Please provide me the solution for this.
Have you even defined pwb and wbs?
Since your website seems to use angularJS, make sure you wait until the site is actually completely generated.
Also, it is likely not a function, but a method of the angular $scope.
So your js code might have to look somewhat like this:
var scope = angular.element($("#outer")).scope();
scope.showOptions()
But the method might expect some kind of "this" or similar of the input element. So I have no idea if this would work.
You might also wanna check:
xx.document.InvokeScript("functionName");

Google Chrome Inspect Element Issue With Hidden ID's

I am not 100% sure if this is as big an issue has I seem to think it is right now but I think I may of found an issue or at else an hole within the Inspect Element viewer within Chrome.
I was using (I have now changed my settings) hidden ID's to set a number of defaults, one was users levels, another was to make the user active by default.
However when I view these ID's within the inspect Element view and then changed the values, submitting the form would submit the NEW value to the server and not the value I had given it.
For Example:
I had something like the following within my code,
<input type="hidden" name="data[user][level][id]" value="1" id="MyID">
I then changed it within the Inspect view to,
<input type="hidden" name="data[user][level][id]" value="2" id="MyID">
Then I submitted the form and was surprised that the NEW value was submitted, I was always under the inpresion that hidden ID's where not changeable and the browser should only submit the default values held within.
I have now changed this to letting the database default to a basic user and then I can change the users setting has I want to. But in some cases this may not be an option, so I was hoping for an answer or some feedback about how to make this more safe.
Am I just a bit slow, are there better methods (different ones) to passing 'hidden' data from forms to the server?
I was thinking about maybe using JQuery to add the needed hidden fields to the forms once the user had selected / submitted the form, but i am not sure if this is 100% safe or even if its a good idea.
Any ideas / feedback are very welcome.....
Many Thanks,
Glenn.
I had the same problem passing the database data into a modal,the solution i know is to use jquery ajax to get the informations from the database requesting a file,adding them into variables and compare the variables
$.ajax({
url: "test.html",
context: document.body
}).done(function() {
$(this).addClass("done");
});
I used this code sample to do it.
Of course there are a few modifications to be done depending on your script
I found a better way of doing this, at lest in CakePHP. The CakePHP framework has inbuilt security calls. These in-built functions when added give you all sorts of stuff but the main reason I used them was to stop this sort of form tampering.
I am not 100% sure how it does this, but it adds a token to all forms and it checks to see if the form being submitted is right? Again not sure how the token works.
But here is the code I used ::
public function beforeFilter() {
$this->Auth->allow('index', 'SystemAccess');
$this->Security->blackHoleCallback = 'blackhole';
}
public function blackhole($type) {
$this->Auth->logout();
$this->Session->setFlash('Sorry a security issue has been detected, please try again or contact us for support.', 'default', array(), 'bad');
$this->redirect($this->Auth->redirect('/'));
}
Now I will add that the call the Auth logout I added to this for extra added security, as the user maybe have logged in on a system and it just not be them that is trying to do things that they should not.
Hope that helps others out!
But this is only a fix for when CakePHP is in use. I would take it that other frameworks would have their options but if your only using basic HTML? or a CMS like Drupal again there might be in built security.
Many Thanks
Glenn.
The only safe and best solution that I found for this issue is to check on the server side whether the user_id sent with the form is the same user_id logged in with or not.
Although using jquery is good idea, but, did not work with my case as am using data: $(this).serialize(),
However here's my code on the server side (Note, am using Laravel 5.4, but am sure it won't matter with your case)
if ($request->user_id != Auth::user()->id)
return json_encode("F**K YOU ! Don't Play Smart -_- !");
else
raw_material_category::create($request->all());
Hope this helped ;)

Preventing form resubmission

Page one contains an HTML form. Page two - the code that handles the submitted data.
The form in page one gets submitted. The browser gets redirected to page two. Page two handles the submitted data.
At this point, if page two gets refreshed, a "Confirm Form Resubmission" alert pops up.
Can this be prevented?
There are 2 approaches people used to take here:
Method 1: Use AJAX + Redirect
This way you post your form in the background using JQuery or something similar to Page2, while the user still sees page1 displayed. Upon successful posting, you redirect the browser to Page2.
Method 2: Post + Redirect to self
This is a common technique on forums. Form on Page1 posts the data to Page2, Page2 processes the data and does what needs to be done, and then it does a HTTP redirect on itself. This way the last "action" the browser remembers is a simple GET on page2, so the form is not being resubmitted upon F5.
You need to use PRG - Post/Redirect/Get pattern and you have just implemented the P of PRG. You need to Redirect. (Now days you do not need redirection at all. See this)
PRG is a web development design pattern that prevents some duplicate form submissions which means, Submit form (Post Request 1) -> Redirect -> Get (Request 2)
Under the hood
Redirect status code - HTTP 1.0 with HTTP 302 or HTTP 1.1 with HTTP 303
An HTTP response with redirect status code will additionally provide a URL in the location header field. The user agent (e.g. a web browser) is invited by a response with this code to make a second, otherwise identical, request to the new URL specified in the location field.
The redirect status code is to ensure that in this situation, the web user's browser can safely refresh the server response without causing the initial HTTP POST request to be resubmitted.
Double Submit Problem
Post/Redirect/Get Solution
Source
Directly, you can't, and that's a good thing. The browser's alert is there for a reason. This thread should answer your question:
Prevent Back button from showing POST confirmation alert
Two key workarounds suggested were the PRG pattern, and an AJAX submit followed by a scripting relocation.
Note that if your method allows for a GET and not a POST submission method, then that would both solve the problem and better fit with convention. Those solutions are provided on the assumption you want/need to POST data.
The only way to be 100% sure the same form never gets submitted twice is to embed a unique identifier in each one you issue and track which ones have been submitted at the server. The pitfall there is that if the user backs up to the page where the form was and enters new data, the same form won't work.
There are two parts to the answer:
Ensure duplicate posts don't mess with your data on the server side. To do this, embed a unique identifier in the post so that you can reject subsequent requests server side. This pattern is called Idempotent Receiver in messaging terms.
Ensure the user isn't bothered by the possibility of duplicate submits by both
redirecting to a GET after the POST (POST redirect GET pattern)
disabling the button using javascript
Nothing you do under 2. will totally prevent duplicate submits. People can click very fast and hackers can post anyway. You always need 1. if you want to be absolutely sure there are no duplicates.
You can use replaceState method of JQuery:
<script>
$(document).ready(function(){
window.history.replaceState('','',window.location.href)
});
</script>
This is the most elegant way to prevent data again after submission due to post back.
Hope this helps.
If you refresh a page with POST data, the browser will confirm your resubmission. If you use GET data, the message will not be displayed. You could also have the second page, after saving the submission, redirect to a third page with no data.
Well I found nobody mentioned this trick.
Without redirection, you can still prevent the form confirmation when refresh.
By default, form code is like this:
<form method="post" action="test.php">
now, change it to
<form method="post" action="test.php?nonsense=1">
You will see the magic.
I guess its because browsers won't trigger the confirmation alert popup if it gets a GET method (query string) in the url.
The PRG pattern can only prevent the resubmission caused by page refreshing. This is not a 100% safe measure.
Usually, I will take actions below to prevent resubmission:
Client Side - Use javascript to prevent duplicate clicks on a button which will trigger form submission. You can just disable the button after the first click.
Server Side - I will calculate a hash on the submitted parameters and save that hash in session or database, so when the duplicated submission was received we can detect the duplication then proper response to the client. However, you can manage to generate a hash at the client side.
In most of the occasions, these measures can help to prevent resubmission.
I really like #Angelin's answer. But if you're dealing with some legacy code where this is not practical, this technique might work for you.
At the top of the file
// Protect against resubmits
if (empty($_POST)) {
$_POST['last_pos_sub'] = time();
} else {
if (isset($_POST['last_pos_sub'])){
if ($_POST['last_pos_sub'] == $_SESSION['curr_pos_sub']) {
redirect back to the file so POST data is not preserved
}
$_SESSION['curr_pos_sub'] = $_POST['last_pos_sub'];
}
}
Then at the end of the form, stick in last_pos_sub as follows:
<input type="hidden" name="last_pos_sub" value=<?php echo $_POST['last_pos_sub']; ?>>
Try tris:
function prevent_multi_submit($excl = "validator") {
$string = "";
foreach ($_POST as $key => $val) {
// this test is to exclude a single variable, f.e. a captcha value
if ($key != $excl) {
$string .= $key . $val;
}
}
if (isset($_SESSION['last'])) {
if ($_SESSION['last'] === md5($string)) {
return false;
} else {
$_SESSION['last'] = md5($string);
return true;
}
} else {
$_SESSION['last'] = md5($string);
return true;
}
}
How to use / example:
if (isset($_POST)) {
if ($_POST['field'] != "") { // place here the form validation and other controls
if (prevent_multi_submit()) { // use the function before you call the database or etc
mysql_query("INSERT INTO table..."); // or send a mail like...
mail($mailto, $sub, $body); // etc
} else {
echo "The form is already processed";
}
} else {
// your error about invalid fields
}
}
Font: https://www.tutdepot.com/prevent-multiple-form-submission/
use js to prevent add data:
if ( window.history.replaceState ) {
window.history.replaceState( null, null, window.location.href );
}

How to clear the form when the user doesn't provide valid username/password

I designed a form as follows:
User Name: _______________
Password: _______________
Login
I also use jQuery Form Plugin to submit the form to the server side.
It will return if the server script finds some errors. The data returned by server is in JSON format. I would like to know how I can reset the user name + password when I know the username/password is invalid in a decent way.
In other words, I can manually use jQuery to empty the username/password field if the returned result indicates a failure. In fact, I am looking for a decent way built in Form Plugin or sth else that can do this part me for automatically. The only thing I have to do is to set a flag so that if the submission is failed, then the form will be resetted.
Thank you
You cam simply do:
$('#form_id').reset();
I don't think you need a plugin for such simple task. You simply call above code based on the response.
Run this.form.reset() when a form button (e.g. Reset) is being pressed.
e.g.
<form>
...
<input type="button" value="Reset!" onclick="this.form.reset();">
</form>