How to avoid multiple submits/posts?

Hello,
How do I prevent previously submitted form data from being reinserted
into
the database when the user presses the browser’s Refresh button?
On Aughey’s advice in #irc I tried using redirect_to' a new :action’
but
this approach doesn’t seems to work.

Any idea what might be wrong or how to tackle this problem?

Thanks for your help.

P.S.- I am using edge rail.

Surendra S.
http://ssinghi.kreeti.com, http://www.kreeti.com
Read my blog at: http://cuttingtheredtape.blogspot.com/
,----
| “All animals are equal, but some animals are more equal than others.”
| – Orwell, Animal Farm, 1945
`----

On 3/21/06, Surendra S. [email protected] wrote:

P.S.- I am using edge rail.

You can do this via a “postback” technique.
The idea is that you use the same action/URL to display the form and
to receive the POSTed results.
Fake example:
def something
@something = Thing.find(params[:id])
if request.post?
@something.attributes = params[:something]
@something.save # or whatever
redirect_to :action => ‘something’
end
end

Here’s a (non-Rails-specific) writeup on how this works:

On Mar 21, 2006, at 12:29 PM, Surendra S. wrote:

Hello,
How do I prevent previously submitted form data from being
reinserted into
the database when the user presses the browser’s Refresh button?
On Aughey’s advice in #irc I tried using redirect_to' a new:action’ but
this approach doesn’t seems to work.

What about that approach isn’t working?


Jason P.
[email protected]

“The computer allows you to make mistakes
faster than any other invention, with the
possible exception of handguns and tequila.”

Jason P. wrote:

On Mar 21, 2006, at 12:29 PM, Surendra S. wrote:

Hello,
How do I prevent previously submitted form data from being
reinserted into
the database when the user presses the browser’s Refresh button?
On Aughey’s advice in #irc I tried using redirect_to' a new:action’ but
this approach doesn’t seems to work.

Insert a unique ID in a hidden field of your form eg
“ADDPRODUCT_XXXXXX”, where XXXX is the unique ID generated by your
application.
When the form is posted, compare the value of the hidden value posted
with the one stored in a session[LASTFORMID]. If values are the same,
don’t add nothing to your database and display an error msg. If values
are not the same, update db and put the hidden value posted in
session[LASTFORMID].

Jason P. [email protected] writes:

What about that approach isn’t working?

With the above approach, if the user reloads the redirected page, the
old form data
still gets reposted, atleast in Mozilla firefox 1.5.

Thanks.

Surendra S.
http://ssinghi.kreeti.com, http://www.kreeti.com
Read my blog at: http://cuttingtheredtape.blogspot.com/
,----
| “All animals are equal, but some animals are more equal than others.”
| – Orwell, Animal Farm, 1945
`----

How about generating a UUID via MD5 or SHA1
based off some random number generation, and
include it in the form as a hidden field.

Then, when a form is posted, store the UUID
in the session after making certain that UUID
doesn’t already exist in the session.


– Tom M.

On about 20% of our IE 6 computers I am having this very weird problem
where form parameters are not POSTing. The POST is empty. Below are
the results. The only thing that has changed between “EMPTY POST” and
“NORMAL POST” is the client computer. And I am seeing cases where the
same client may work at a later date. Has anyone seen this? It is
making me want to pull my hair out!!

EMPTY POST:

Processing AdministratorsController#create2 (for 10.6.15.17 at
2006-03-21 16:48:10) [POST]
Parameters: {“action”=>“create2”, “controller”=>“administrators”}
e[4;35;1mAdministrator Columns (0.015000)e[0m e[0mSHOW FIELDS FROM
administratorse[0m
params for administrator/create: {“action”=>“create2”,
“controller”=>“administrators”}


NORMAL POST:

Processing AdministratorsController#create2 (for 10.15.100.25 at
2006-03-21 16:46:23) [POST]
Parameters: {“commit”=>“Create”, “action”=>“create2”,
“administrator”=>{“name”=>“John D.”, “is_active”=>“true”,
“email”=>“[email protected]”}, “controller”=>“administrators”}
e[4;36;1mAdministrator Columns (0.016000)e[0m e[0;1mSHOW FIELDS
FROM administratorse[0m
params for administrator/create: {“commit”=>“Create”,
“action”=>“create2”, “administrator”=>{“name”=>“John D.”,
“is_active”=>“true”, “email”=>“[email protected]”},
“controller”=>“administrators”}


create2 controller

def create2
@administrator = Administrator.new(params[:administrator])
logger.info "params for administrator/create: " + params.inspect
@administrator.time_of_creation = Time.now
if @administrator.save
flash[:notice] = ‘Administrator ’ + @administrator.name + ’ was
successfully created. Please assign a user id.’
redirect_to :action => ‘edit’, :id => @administrator.id
else
render :action => ‘new’
end
end


new2.rhtml

New administrator

<%= start_form_tag :action => ‘create2’ %>
<%= render :partial => ‘form’ %>
<%= submit_tag “Create” %>
<%= end_form_tag %>

<%= link_to ‘Back’, :action => ‘list’ %>


_form.rhtml

<%= error_messages_for ‘administrator’ %>

Name
<%= text_field 'administrator', 'name' %>

Email
<%= text_field 'administrator', 'email' %>

Active
<%= options_for_select({"False" => false, "True" => true}, @administrator.is_active) %>

The answer to this question btw is:

Form submission error with MSIE 6.0 (post data)

Problem

With MSIE 6, form is posted with empty data (sporadical)

Possible causes and solutions

  1. You cannot post any data to mixed NTLM and non-NTLM authenticated
    Web sites. Microsoft Internet Explorer requires NTLM
    authentication for all visits to a website after you visit one
    NTLM authenticated folder of the website.

    MSIE 5 or later has a feature called NTLM pre-authorization which
    lets the browser cache credentials if an NTLM challenge is
    received. Subsequent requests use the cached credentials.

  2. If you post a form via an ASP page, to IIS 4.0, and a sub folder
    on the site does not use NTLM (but the parent does), the browser
    does not send the POST data to the server. To solve this problem,
    use Regedt32 to navigate to:

    HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet
    Settings

    On the Edit menu, Add Value name DisableNTLMPreAuth as a type
    REG_DWORD and set the data value to 1 (true).

  3. This is actually in IE, and not a problem on the server side. Once
    NTLM authentication has been negotiated, the client browser will
    renegotiate authentication before sending the POST data.
    Basically, there is a handshake during initial authentication.
    When you do a form POST at any point after that, the client
    reinitiates the handshake (with the empty POST). The server
    responds with a challenge, and the client then resubmits the POST
    with the form data (and the response to the challenge in the
    authorization header).

    It seems, any NTLM authentication to a server will result in this
    behavior for subsequent POSTs to the same server (even unprotected
    resources). For example, if I go to NTLM-protected resource
    “/myntlm/test.html”, then (later on) POST to the unprotected
    resource “/unprotected/foo.asp” this will be exhibited.

    The only way I have seen to get IE to “forget” it has previously
    NTLM-authenticated to a site is to send a 401 page status. This
    effectively resets the IE authentication state.

  4. Microsoft Support

  5. Use KeepAlive off on the server (Apache).

Surendra S. wrote:

On Aughey’s advice in #irc I tried using redirect_to' a new:action’ but
this approach doesn’t seems to work.

What about that approach isn’t working?

With the above approach, if the user reloads the redirected page, the old form data
still gets reposted, atleast in Mozilla firefox 1.5.

Thanks.

Do you have the AWDWR book? If so, you might look at the discussion of
redirect-on-post on
pages 309-310. Otherwise, there’s bound to be plenty of resources
online.

Basically, I remember it like this:

A browser displays an html page. It knows what page this is by its URL,
which you can see
in the address bar. If that page has a form, it will have an “action”
attribute with the
value being the URL the browser should “post” a request to when the
form’s submitted.

After submitting, the server does it’s processing and sends a response.
The browser is
more than happy to treat that response as a new page to display, with
its URL being the
one specified in the “action” attribute. If the user then hits refresh,
the browser asks
the server for the page indicated in its address bar, which is the post
url for the
form… so the form is posted again.

So instead what we do is always make sure the response from a post is
a redirect,
telling the browser “thanks for your submission and by the way here’s
where you can view
the answer to your post”. This way the URL in the address bar is always
a view URL or
“get” request.

Hope I’m not being too pedantic here… But if you still think the
redirect isn’t working,
you might start by posting the URL of your form page, the URL of the
action attribute of
the form tag, and what’s in the address bar after a submission.

b

PS: there are also several firefox plugins to view HTTP headers…
LiveHTTP Headers,
Tamper Data to name two. With that you can see if the browser is being
redirected.