2009-05-20 16 views
20

Un problema Web comune è quando un utente fa clic più volte sul pulsante di invio di un modulo in modo che il server elabori il modulo più di una volta. Ciò può anche accadere quando un utente preme il pulsante Indietro dopo aver inviato un modulo e quindi viene elaborato nuovamente.Quali metodi sono disponibili per arrestare più postback di un modulo in ASP.NET MVC?

Qual è il modo migliore per impedire che ciò accada in ASP.NET MVC?

possibilità come la vedo io sono:

  1. disattivare il pulsante dopo aver presentare - questo ottiene intorno alle più clic, ma non la navigazione
  2. Avere l'azione di ricezione reindirizzare immediatamente - i browser sembrano lasciare queste redirezioni fuori della storia
  3. Posizionare un token univoco nella sessione e sulla forma - se corrispondono elaborare il modulo - se non cancellare il modulo per un nuovo presentare

Ce ne sono altri?

Esistono alcune implementazioni specifiche di uno di questi?

Riesco a vedere la terza opzione implementata come ActionFilter con un'estensione HtmlHelper in modo simile a quella anti-contraffazione.

In attesa di sentire da voi MVC fuori là.

risposta

16

Spesso le persone si affacciano il modo più convenzionale per gestire questa situazione, che è quello di utilizzare chiavi nonce.

È possibile utilizzare PRG come altri hanno detto, ma il lato negativo con PRG è che non risolve il problema del doppio clic, si richiede un viaggio in più per il server per il reindirizzamento, e dal momento che l'ultimo passo è una richiesta GET non si ha accesso diretto ai dati appena pubblicati (sebbene possa essere passato come parametro di query o mantenuto sul lato server).

Mi piace la soluzione Javascript perché funziona più del tempo.

Le chiavi non valide tuttavia, funzionano sempre. La chiave nonce è un GUID univoco casuale generato dal server (anch'esso salvato nel database) e incorporato nel modulo. Quando l'utente invia il modulo, viene inviata anche la chiave nonce. Non appena un POST arriva al server, il server verifica che la chiave nonce esista nel suo database. In caso affermativo, il server elimina la chiave dal database ed elabora il modulo. Di conseguenza, se i POST utente sono due volte, il secondo POST non verrà elaborato perché la chiave nonce è stata cancellata dopo l'elaborazione del primo POST.

La chiave nonce ha un ulteriore vantaggio in quanto offre maggiore sicurezza impedendo replay attacks (un uomo nel mezzo annusa la richiesta HTTP e quindi la riproduce sul server che la considera legittima).

+0

Idea interessante, una cosa che vorrei aggiungere è che dovresti inserire la sequenza in una transazione: 1) controlla nonce 2) processo 3) cancella nonce. Se non lo fai atomicamente hai una condizione di gara in cui il post può essere elaborato più volte, esp. se l'elaborazione richiede un po 'di tempo per finire (e l'utente è impaziente). Una cosa su cui non sono ancora chiaro è se il POST rileva una duplicazione, cosa deve essere restituito all'utente? Una pagina che indica che il post è in corso? – DSO

+0

Prima cancellerei la chiave nonce e poi eseguirò l'elaborazione per mantenere le cose semplici. Come gestire un dupe è una decisione di progettazione e fino a voi. Tuttavia, una risposta descrittiva di ciò che è appena successo potrebbe aiutare l'utente ad apprezzare ancora di più la tua app Web. – aleemb

+0

Hai mai visto un'implementazione di chiavi nonce in ASP.NET MVC utilizzando ActionFilters? Posso immaginare che ciò renderebbe l'implementazione molto semplice e riutilizzabile. Potrebbe anche utilizzare un DB o semplicemente una variabile di sessione. – WooWaaBob

1

Questo non è proprio MVC specifico, ma lo schema che seguiamo sulle nostre pagine web è che le azioni vengono eseguite con chiamate AJAX, piuttosto che con POST a pagina intera. Quindi navigare in un URL non esegue mai un'azione, mostra solo il modulo. La chiamata AJAX non sarà nella cronologia

0

Insieme alla disattivazione dei pulsanti, è possibile aggiungere un div trasparente su tutta la pagina Web in modo che il clic non faccia nulla. Lo facciamo al mio lavoro e aggiungiamo un'etichetta amichevole che dice richiesta di elaborazione.

5

Si dovrebbe sempre restituire un reindirizzamento come risposta HTTP a un POST. Ciò impedirà al POST di verificarsi nuovamente quando l'utente naviga avanti e indietro con i pulsanti Avanti/Indietro nel browser.

Se si è preoccupati che gli utenti facciano doppio clic sui pulsanti di invio, è sufficiente che uno script piccolo li disabiliti immediatamente al momento dell'invio.

+0

E il nostro non js belle utenti? – redsquare

+0

Gli script possono essere non intrusivi e inseriti in modi che non disturbano i browser/utenti non js. Se si è ancora preoccupati per l'invio di moduli doppi, è necessaria una logica lato server per gestirli. – mookid8000

+0

questo è quello che stavo ottenendo. La logica è meglio implementata lato server che basandosi su js – redsquare

2

Si potrebbe desiderare di guardare il (PRG) modello Post-Redirect-Get:

+1

Il pattern PRG non risolve il problema di fare clic sull'inviamento dell'utente più volte. – DSO

+0

No, non lo fa - risolve il problema del pulsante indietro anche se –

+0

si può facilmente evitare il doppio clic con una semplice funzione javascript. – josephdotca

Problemi correlati