How to prevent multiple posts on MVC3? - c#

A user wants to post in his blog, he fills the field and click submit.
The site is running slow, he clicks again, and again, and again.
It was finally saved, but now he check his posts and sees 4 posts.
How can I prevent this from happening? If the user click to submit once I want to do nothing for the next clicks or abort previous and start a new post, whichever makes more sense or is recommended.
In a form with
#using (Ajax.BeginForm(...))
{
}

The easiest way to achieve this is to disable submit buttons after click.
Add the following javascript (jQuery) to your view:
$(function () {
$('input[type="submit"]').click(function() {
$(this).attr('disabled', 'disabled');
});
});
Remember to enable buttons after ajax request complete if neccessary:
$('input[type="submit"]').removeAttr('disabled');
UPDATE:
It's better to disable the submit button in forms submit event handler, because an user can submit the form by pressing enter button:
$(function () {
$('form').submit(function() {
$('input[type="submit"]', this).attr('disabled', 'disabled');
});
});

There are many solutions.
One is to create a random GUID with
the form as a hidden field which is
inserted into database with the post.
Before inserting, it checks if GUID
already exists.
Alternatively you can use a real property such as DateTime (which is sent to the client side as a hidden field) or "Post title".

How about the minute the user clicks on the action link for the post area you create a real post but set its "Status" to draft?. After you InsertOnSubmit() the post immediately redirect to an action which you retrieve the post and edit it. This happens so fast the user will not notice. So if the site is slow and he clicks on "Submit" multiple times you will not be generating new records just saving to the same record. I using the process on an task list application I working on. See the code below.
Better Task List Ticket Controller
It may not be the fanciest solution but could lead you to a more creative solution that works for you.

My vote is for ActionFilters. This blog post has code to just drop into your project and decorate your actions.

Related

Prevent resending form without page.redirect

maybe some of you know the problem, that a form gets resubmitted if pressing refreshing the browser by pressing F5.
I am looking for a way to prevent this, and all I have found is the solution to do a redirect on the same page after submit
Response.Redirect(Request.RawUrl);
This DOES work, but my problem is, that I need to inject javascript into a placeholder after postback, and so this information is lost because of the Redirect.
PlaceHolder p1 = this.NamingContainer.Parent.FindControl("phPostScript") as PlaceHolder;
GenerateJsTag(script,p1);
Response.Redirect(Request.RawUrl);
Is there a way I can prevent a resubmit without Redirect?
Thanks
Is there a way I can prevent a resubmit without Redirect?
Even if there is , you should stick to that approach which is redirect after submit.
Regarding JS after post back , I believe that you want to see those JS output even after refresh after redirect.
What you can do is to redirect to Request.RawUrl+"#someValue" and then in the pageLoad (not within IsPostBack) you can inject again those scripts , knowing that you already showed that to the user via that hashkey ( could be cookie also , or query string , doesn't really matter) - or to show a message like ("Message was already accepted"...) or something like that.
Try adding following JavaScript code to your aspx page.
Also, you should not be trying to disable F5 since there are many users out there who may need to use F5 during browsing with your website.
//bind keydown event to method that disables F5
$(document).on("keydown", PreventRefresh);
function PreventRefresh(e) {
var code = e.which || e.keyCode;
if (code === 116) {
e.preventDefault();
}
}

Clear POST data after submission so user can't click Back in browser

My form when redirected to the thank you page after completion seems to retain all the data in the values field so if the user clicks back everything is there meaning they can just resubmit it and its super annoying.
if (emailSent) {
Response.BufferOutput = true;
Response.Redirect("MYDOMAIN/redirect.aspx");
};
Above is where I redirect after the form has been submitted. For my code to pull the data I am using:
Request.Form[randomFormField]
When I redirect and then click back everything is there.
$(".submitBut").click(function() {
$(this).closest('form').find("input[type=text], textarea").val("");
window.location.href('MYREDIRECTDMAIN/redirect.aspx');
});
Above is another one of my attempts
I have tried a variety of different things and nothing seems to work. I need an ASP.NET solution or C# or JQuery.
Javascript on page load: clear all form fields
Uhm....
$(document).ready(function() {
$(':input').val('');
});
References:
Input
Clearing

MVC 4 with jQuery Mobile page seems to be caching and controller method not being called

EDIT
Figured it out.. $.ajaxSetup({ cache: false }); wasn't working because i had data-ajax set to turned off on the form and therefore i wasn't able to set no cache ajax on it.. just for completeness if anybody knows how to get this done WHILE dada-ajax is set to false then please post so here
Something else that I just tried and it worked was to simply add data-ajax="false" to any link that you want a page refresh on. Meaning that if I have data-ajax="false" on a link it will always refresh the page before showing it!
For example the link I had a problem with was
Add a new weekly update
and the problem was that for some reason that page was caching and always showing the cached page.. So one of the easy fixes was to add data-ajax="false" to it and that forced a reload of the page everytime
Add a new weekly update
````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
Question:
I have a options menu which brings up a form which also has a cancel and submit button.
Once the form is submitted there is certain validation that runs and if something is missing it returns to the form with some validation text.
Now if I click the cancel button at anytime i should be brought back to the options menu and if I click on the same button that brings up the form i should see a brand new clean form and this works fine if I do it before the validation.
The problem is that if I submit a non valid form which returns with the error validation messages and THEN press cancel it seems that the page becomes cached or something similar because from that point on anytime I click on the form options menu button the same form shows up each with the validation errors and data. I put a break point in the method that returns the form View() and they are never hit so for some reason it skips the entire method which creates a new form and somehow just shows the old page.
The cancel button is the following
Cancel
Does anybody know what is happening? is it being cached somehow when it returns to the same page with the validation errors??
** EDIT **
I Tried adding [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] in front of the controller by to no avail..
I also now added
$.ajaxSetup({ cache: false });
to the top of my $(document).ready(function () but that also does not seem to be doing anything, do I just put it there or do I have to call it somehow?
I checked System.Web.HttpContext.Current.Cache and the page doesn't show up there.
Have you tried setting the output cache options on the controller action like
[OutputCache(Duration=600,VaryByParam="id")]
You might also want to try making sure jquery is not caching the request as well. You can globally turn off jquery ajax caching using the information here: How to set cache: false in jQuery.get call
You can try using $.mobile.changePage() to transition to the page, it allows you to set some options, one of which is reloadPage.
reloadPage (boolean, default: false) Forces a reload of a page, even if it is already in the DOM of the page container. Used only when
the 'to' argument of changePage() is a URL.
Source: http://jquerymobile.com/demos/1.1.1/docs/api/methods.html
You could work this into your link with something like:
<script>
function changeMyPage(url) {
$.mobile.changePage(url, { reloadPage : true });
}
</script>
Cancel
jquery Mobile pulls multiple pseudo-pages into the DOM at one time and normally deletes (.removes()) a pseudo-page after you've navigated away from it. It however sounds like that's not happening so you may need to use my above code (or something similar) to force a refresh of the page.
You need to clear your ModelState before hand.
This should work:
if (ModelState.IsValid)
{
//saving
if (result > 0)
{
**ModelState.Clear();**
return View(new CategoryViewModel());
}
}
How to Clear model after submit the data in database in MVC3

asp.net: how do i prevent users from posting the same data multiple times

i have a little asp.net web application.
it is a front end to a sql-server-2008 database.
after they fill out all the data, they will press submit and the data will be sent to the database.
after this point if the user refreshes the page, the data is posted again!!! how do i disable this from happening?
Send a Location header back to the user that redirects the browser to another page: refresh will then reload that other page rather than resubmit the old form.
This is caused by the last request being a POST request to the page, what do you need to do is a redirect so the last request becomes a GET.
After you have handled the post data you can just do a redirect to the same page with:
Response.Redirect("~/ThePage.aspx");
This will prevent you from presenting a message to the user straight from the code behind, if you want to present a success message using this method you will need to add a querystring or something similar:
Response.Redirect("~/ThePage.aspx?result=success");
And then check on the page bind if the querystring to present a success message is set, such a check could look something like this:
if (Request.QueryString["result"] != null && Request.QueryString["result"].ToString().ToLower() == "success")
{
//Show success message
}
Another solution which probably is superior but might require some more work is to wrap the form in a updatepanel, you can read more about it here: http://ajax.net-tutorials.com/controls/updatepanel-control/
An updatepanel will make the form submit with AJAX instead of full postback.
You need to follow the Post/Redirect/Get pattern which is explained on WikiPedia and alluded to by Femi. In your code after you've done your processing do a Response.Redirect to the desired page.
See this article about the PRG pattern: http://en.wikipedia.org/wiki/Post/Redirect/Get
In short, after the user POSTs (submits) data to your server, you issue a Response.Redirect to have the users browser GET a page. This way, if the user presses the reload button, it is the GET request that is repeated.

Disable selection box without removing value from post

In my current asp.net-mvc project one of my pages allows the user to select a value in a dropdown box after wich a post request is made that updates several values.
To make sure the delay from the postback doesn't confuse the user into selecting another value (and thus creating another post, creating another delay etc) I set the select's disabled attribute to true.
Disabled inputs aren't submitted to the post call however.
How can I make it visually clear to the user that work is in progress and make it imposible to select a new value without removing the input from the post?
Yes, this annoys me too.
Basically what you need to do is hide the old button and replace it with a disabled one so it looks the same to the user. That way it's still submitted but can't be doubly submitted.
Actually I've found what seems to be a duplicate of this at Problem with disabling submit buttons on form submit.
From your answer, I gather you are already using jQuery. In that case why don't you get the value of the select box, disable it, then post the value yourself?
Bonus : BlockUI is a nice jQuery plugin to, well, block the UI.
None of the answers I found in Cletus' post was entirely what I was looking for.
Here is what I came up with. It's not 100% reusable, but it does what I need and feel free to improve/edit.
$('#productMixSelectorForm').change(function() { $(this).ChangeSelection() });
jQuery.fn.ChangeSelection = function() {
var html = $('<div class="hidden">');
$(this).find('select, input').each(function() {
if ($(this).hasClass('hidden') == false) {
//Clone the original one into the hidden div
html.append($(this).clone());
//Disable the original (visible) one and make it's name unique again
$(this).attr("disabled", true);
var name = $(this).attr("name");
$(this).attr("name", name + "disabledDummy");
}
});
//Add the collection of clones to the form so they get submitted
$(this).append(html);
$(this).submit();
}

Categories