2012-03-21 8 views
5

Ho un 3 applicazione ASP.NET MVC, che ha un'azione post chiamato Create:evitare la doppia forma osservazioni

[HttpPost] 
public virtual ActionResult Create(Issues issues) 
{ 
    if (ModelState.IsValid) 
    { 
     context.Issues.Add(issues); 
     context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(issues); 
} 

Se faccio doppio clic sul pulsante di invio per errore, si creerà problemi di 2x. C'è un modo per prevenirlo, senza l'uso di javascript e disabilitando il pulsante, ho pensato che l'intero uso dell'uso di RedirectToAction era quello di prevenire questo, utilizzando il modello di progettazione Post/Redirect/Get?

+1

puoi semplicemente aggiungere qualcosa come se (! Context.Issues.Exists (logic))? –

+1

Basta disattivare il pulsante di invio quando si fa clic! – gdoron

+0

Non esiste un metodo chiamato Exists? – CallumVass

risposta

4

pagina Il modello hai citato (Post/Redirect/Get design pattern) impedisce rinfresca dal doppio distacco, perché l'ultima azione è una GET, non il POST.

Se si vuole evitare che un doppio clic da doppio distacco, si potrebbe:

1. Disable the button after click 
2. Maintain a unique index on 'Issues' and look for duplicates 
3. Maintain something in session that gives you an indication of a double post 

E là forse un paio di modi ... Penso che la disattivazione del tasto è probabilmente il più facile perché si comunque reindirizzando verso un'altra pagina.

+0

Questo va bene per l'esempio sopra, ma il punto che stavo ottenendo è per esempi più avanzati, ad esempio Ajax.BeginForm che aggiornerà solo parte di una pagina – CallumVass

+0

@BiffBaffBoff - Per evitare il doppio clic sul lato client (AJAX POST), puoi semplicemente bloccare l'interfaccia utente fino a quando la risposta non ritorna (sincrona) o disabilitare il pulsante (asincrono) o implementare qualcosa sul lato server per rilevarlo. –

+0

Ciao Chris, questo è esattamente quello che ho fatto ora. Ho disabilitato il pulsante fino a quando la risposta è tornata. Grazie ancora – CallumVass

1

È possibile generare un IssueId quando si mostra il modulo all'utente, quindi controllare di non avere già un problema con tale id nel metodo Create e, ad esempio, saltare tali richieste.

+0

Beh, creerà solo l'aggiunta di Id's come IssueId è il mio campo PK quindi per ogni nuovo Issue creato, avrà un nuovo Id (2, 3, 4, 5 ecc.) – CallumVass

2

più semplici modo che posso pensare è utilizzare la sessione:

if (ModelState.IsValid) 
{ 
    DateTime now = DateTime.Now; 
    if (Session["LastAdd"] == null || (now - (DateTime)Session["LastAdd"]).TotalMilliseconds > 1000) 
    { 
     //first time, or more than a second passed since last addition 
     context.Issues.Add(issues); 
     context.SaveChanges(); 
     Session["LastAdd"] = now; 
    } 
    return RedirectToAction("Index"); 
} 
+0

Spiacente, non uso sessioni come un'applicazione di autenticazione di Windows – CallumVass

+0

@BiffBaffBoff - Inizia a utilizzare le variabili 'Session'. –

+0

@Biff Le variabili di sessione non hanno nulla a che fare con l'autenticazione. cosa ti fa pensare in questo modo? –

5

facile soluzione!

Disattivare il pulsante di invio quando viene fatto clic. The End.

$('submitButtonId').click(function(){ 
    $(this).prop('disabled', true); 
    $(this).attr('disabled', 'disabled'); // for jQuery versions < 1.6. 
}); 
+1

Con questa soluzione, se l'utente ha un problema di rete tra il clic e il caricamento delle informazioni sul server, non c'è modo di recuperare le informazioni nel modulo. Se l'utente ha appena trascorso 5 minuti a compilare il modulo, sarà sconvolto. Un approccio migliore è probabilmente solo disabilitarlo fino a quando la rete ha esito positivo o negativo. –

+0

Non funzionerà con JavaScript disabilitato? –

+0

@AlexAngas, nulla funzionerà quando javascript è disabilitato. Non penso che ci sia un buon modo di farlo senza js. (La risposta di _Shadow Wizard_ qui sotto è hard coding 1000 ms, che è lontano dall'essere l'ideale, e se l'utente ha una connessione di rete lenta?) – gdoron

0

Il pattern PRG non impedisce questo, poiché l'azione P in esso richiede tempo (che di solito è il caso) e l'utente può inviare nuovamente il modulo (tramite clic o aggiornamento del browser), che farà sì che il modello PRG "fallire".

Si noti che gli utenti malintenzionati possono anche bypassare tutte le misure del lato client eseguendo più post http in rapida successione.

Una soluzione a tutti i precedenti è di verificare la presenza di invii duplicati sul lato server utilizzando il seguente metodo, come descritto da me stesso, here.

Per comodità, cito:

"Se fai uso di un token anti-contraffazione nascosta nel modulo (come si dovrebbe), è possibile memorizzare nella cache l'anti-contraffazione token prima submit e rimuovere il gettone dalla cache, se necessario, o scade la voce memorizzata nella cache dopo certo lasso di tempo.

Sarete quindi in grado di controllare con ogni richiesta contro la cache se la forma specifica è stata presentata e rifiutarlo se lo ha. "

Problemi correlati