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 ...
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:
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%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.
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.
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.
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.
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 ...;)
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.
Tags und Links asp.net-mvc c# form-submit