Was ist eine gute Methode, um zu verhindern, dass ein Benutzer ein Formular zweimal absendet?

8

Ich habe eine Kaufseite, und ich möchte nicht, dass der Benutzer die Seite aktualisieren und das Formular erneut senden kann, sobald sie die Seite 'Bestellung abgeschlossen' erreicht haben, weil sie sie automatisch über Datenbankwerte und in unserem System einrichtet lädt ihre Karte per Paypal (nur wollen diese EINMAL passieren) ... Ich habe einige Seiten gesehen, die sagen: "Nicht auffrischen drücken oder Sie werden doppelt aufgeladen!" aber das ist ziemlich lahm, es offen zu lassen, was ist eine gute Möglichkeit, es nur einmal zuzulassen oder zu verhindern, dass sie sich auffrischen, usw.?

PS: Ich habe ein paar ähnliche Fragen gesehen: PHP: Stoppen Sie die versehentliche erneute Verarbeitung eines Formulars, wenn Zurück gedrückt wird und Wie verhindere ich, dass die Schaltflächen Zurück und Aktualisieren das Formular erneut senden? , aber keine zufriedenstellende Antwort gefunden haben ... eine ASP.NET MVC-spezifische Antwort Ideal auch sein, wenn es einen Mechanismus dafür gibt.

BEARBEITEN: Sobald sie auf "submit" klicken, sendet sie einen POST an meinen Controller und dann macht der Controller etwas Magie und gibt dann eine Ansicht mit einer Nachricht "Auftrag abgeschlossen" zurück, aber wenn ich auf "Aktualisieren" in meinem Browser klicke, wird der gesamte Vorgang erneut gesendet diese Form?' das ist schlecht ...

    
BigOmega 21.01.2010, 19:32
quelle

9 Antworten

17

Die Standardlösung dafür ist das POST / REDIRECT / GET -Muster. Dieses Muster kann mit so gut wie jeder Web-Entwicklungsplattform implementiert werden. Sie würden normalerweise:

  • Validierung der Einreichung nach POST
  • falls es nicht gelingt, das ursprüngliche Eingabeformular mit angezeigten Validierungsfehlern erneut zu rendern
  • wenn es erfolgreich ist, REDIRECT auf eine Bestätigungsseite oder Seite, auf der Sie die Eingabe erneut anzeigen - dies ist der GET-Teil
  • Da die letzte Aktion ein GET war, wird der Benutzer zu diesem Zeitpunkt nicht aktualisiert, wenn eine erneute Aktualisierung des Formulars erfolgt.
RedFilter 21.01.2010, 19:37
quelle
12

I stimme zu 100% der generischen Antwort von RedFilter zu, wollte aber speziell für ASP.NET MVC relevanten Code veröffentlichen.

Sie können das Post / Redirect / Get (PRG) Muster verwenden, um das Problem des doppelten Postbacks zu lösen .

Hier ist eine grafische Darstellung des Problems:

Was passiert, wenn der Benutzer auf die Aktualisierung klickt, versucht der Browser, die letzte Anforderung erneut zu senden. Wenn die letzte Anfrage ein Post war, wird der Browser versuchen, dies zu tun.

Die meisten Browser wissen, dass dies normalerweise nicht das ist, was der Benutzer tun möchte, also wird automatisch gefragt:

  

Chrome -   Die von Ihnen gesuchte Seite verwendet die von Ihnen eingegebenen Informationen.   Wenn Sie auf diese Seite zurückkehren, wird möglicherweise jede Aktion wiederholt.   Möchten Sie fortfahren?
Firefox - Um diese Seite anzuzeigen, muss Firefox Informationen senden, die eine zuvor durchgeführte Aktion (z. B. eine Suche oder eine Auftragsbestätigung) wiederholen.
< stark> Safari -   Möchten Sie das Formular wirklich erneut senden?   Um diese Seite erneut zu öffnen, muss Safari ein Formular erneut senden. Dies kann zu doppelten Käufen, Kommentaren oder anderen Aktionen führen.
Internet Explorer -   Um die Webseite erneut anzuzeigen, muss der Webbrowser   Senden Sie die Informationen erneut, die Sie zuvor übermittelt haben.   Wenn Sie einen Kauf getätigt haben, sollten Sie auf Abbrechen klicken   Vermeiden Sie eine doppelte Transaktion. Klicken Sie andernfalls auf Wiederholen, um angezeigt zu werden   die Webseite erneut.

Das PRG-Muster hilft jedoch, dies zu vermeiden, indem dem Client eine Umleitungsnachricht gesendet wird. Wenn die Seite schließlich erscheint, war die letzte vom Browser ausgeführte Anfrage eine GET-Anforderung für die neue Ressource.

Hier ist ein toller Artikel auf PRG , die eine Implementierung des Musters für MVC bietet. Es ist wichtig zu beachten, dass Sie nur auf eine Weiterleitung zurückgreifen möchten, wenn auf dem Server eine nicht idempotente Aktion ausgeführt wird. Mit anderen Worten, wenn Sie ein gültiges Modell haben und die Daten in irgendeiner Weise beibehalten haben, ist es wichtig, sicherzustellen, dass die Anfrage nicht versehentlich zweimal gesendet wird. Wenn das Modell jedoch ungültig ist, sollten die aktuelle Seite und das aktuelle Modell zurückgegeben werden, damit der Benutzer die erforderlichen Änderungen vornehmen kann.

Hier ist ein Beispiel Controller:

%Vor%     
KyleMit 09.02.2015 20:11
quelle
2

Während Sie die Bestellbestätigungsseite aufrufen, können Sie ein Token festlegen, das Sie auch im DB / Cache speichern. Überprüfen Sie bei der ersten Bestätigung der Bestellung, ob dieses Token existiert und löschen Sie das Token. Bei Implementierung mit Thread-Sicherheit können Sie die Bestellung nicht zweimal absenden.

Dies ist nur einer der vielen möglichen Ansätze.

    
Sands 21.01.2010 19:35
quelle
1

Geben Sie jedem Besucherformular beim ersten Laden der Seite eine eindeutige ID. Notieren Sie die ID, wenn das Formular gesendet wird. Sobald ein Formular mit dieser ID gesendet wurde, lassen Sie keine weiteren Anfragen mehr zu. Wenn sie auf Aktualisieren klicken, wird dieselbe ID gesendet.

    
Macha 21.01.2010 19:35
quelle
1

Beachten Sie, dass das PRG-Muster nicht vollständig vor Mehrfachformularen schützt, da mehrere Postanfragen abgefeuert werden können, noch bevor eine einzelne Weiterleitung stattgefunden hat - dies kann dazu führen, dass Ihre Formulareinreichungen nicht idempotent .

Beachten Sie die Antwort, die zur Verfügung gestellt wurde hier , die einen Workaround für dieses Problem bietet, den ich hier aus praktischen Gründen zitiere:

  

Wenn Sie ein verstecktes Fälschungs-Token in Ihrem Formular verwenden (wie Sie   sollte), können Sie das Anti-Fälschungs-Token beim ersten Senden und   Entfernen Sie ggf. das Token aus dem Cache, oder verfallen Sie den zwischengespeicherten Eintrag   nach der eingestellten Zeit.

     

Sie können dann mit jeder Anfrage gegen den Cache überprüfen   ob das spezifische Formular eingereicht wurde und es ablehnen, wenn dies der Fall ist.

     

Sie müssen keine eigene GUID generieren, da dies bereits erfolgt   wenn das Anti-Fälschungs-Token generiert wird.

    
Daffy Punk 05.05.2016 16:57
quelle
0

Mache einfach eine Weiterleitung von der Seite, die all die üblen Sachen macht, auf die Seite "Danke für deine Bestellung". Danach kann der Benutzer so oft aktualisieren wie er möchte.

    
Klaus Byskov Pedersen 21.01.2010 19:37
quelle
0

Wenn Sie den Nutzer nicht auf eine andere Seite umleiten möchten, dann , indem Sie meinen Weg verwenden, brauchen Sie Post / Redirect / Get nicht (PRG) Pattern und der Nutzer bleibt auf der aktuellen Seite ohne Angst vor den negativen Auswirkungen der erneuten Einreichung des Formulars!

Ich verwende einen TempData -Eintrag und einen Hidden field (eine Eigenschaft im ViewModel des Formulars), um ein gleiches Guid auf beiden Seiten zu behalten ( Server/Client ) und es ist mein Zeichen, um zu erkennen, ob Das Formular wird erneut durch Aktualisieren ersetzt oder nicht.

Die letzte Seite der Codes sieht sehr kurz und einfach aus:

Aktion:

%Vor%

In der Ansicht:

%Vor%

Im Ansichtsmodell:

%Vor%

Was denkst du?

Ich mache es einfach, indem ich 2 Klasse schreibe:

  • NoResubmitAbstract abstrakte Klasse
  • ControllerExtentions statische Klasse (Eine Erweiterungsklasse für System.Web.Mvc.ControllerBase )

ControllerExtentions:

%Vor%

NoResubmitAbstract:

%Vor%

Setz sie einfach in dein MVC-Projekt und starte es ...;)

    
RAM 13.06.2017 02:22
quelle
-1

Aus der Spitze meines Kopfes, generieren Sie eine System.Guid in einem versteckten Feld auf der GET-Anfrage der Seite und verknüpfen Sie es mit Ihrer Kasse / Zahlung. Überprüfen Sie es einfach und zeigen Sie eine Nachricht mit dem Titel "Zahlung bereits bearbeitet" an. oder so.

    
Wim Hollebrandse 21.01.2010 19:36
quelle
-1

Kazi Manzur Rashid schrieb über Dies (zusammen mit anderen Best Practices von asp.net mvc). Er schlägt vor, zwei Filter zu verwenden, um die Datenübertragung zwischen dem POST und dem folgenden GET mit TempData zu behandeln.

    
Nasser 22.01.2010 13:38
quelle

Tags und Links