2012-03-21 19 views
5

que tienen una aplicación ASP.NET MVC 3, que tiene una acción posterior a la llamada Create:evitar la doble envíos de formularios

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

Si hago doble clic en el botón de envío por error, se va a crear problemas de 2x. ¿Hay alguna manera de prevenir esto, sin el uso de javascript y deshabilitando el botón, pensé que el uso total de usar un RedirectToAction era para evitar esto, mediante el uso del patrón de diseño Publicar/Redirigir/Obtener?

+1

puede simplemente agregar algo como if (! Context.Issues.Exists (logic))? –

+1

¡Simplemente deshabilite el botón de enviar cuando se haga clic! – gdoron

+0

No existe tal método llamado Exists? – CallumVass

Respuesta

4

página El patrón que usted ha mencionado (Mensaje/Redirigir/Obtener patrón de diseño) impide que refresca de doble desplazamiento debido a que la última acción es un GET, no el POST.

Si desea evitar que hace doble clic de doble desplazamiento, usted podría:

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 

Y allí quizá algunas de las formas más ... Creo que deshabilitar el botón es probablemente el más fácil porque usted Estamos redireccionando a otra página de todos modos.

+0

Esto está bien para el ejemplo anterior, pero el punto al que me refería es para ejemplos más avanzados, por ejemplo Ajax.BeginForm que solo actualizará parte de una página – CallumVass

+0

@BiffBaffBoff - Para evitar hacer doble clic en el lado del cliente (AJAX POST), simplemente podría bloquear la IU hasta que la respuesta regrese (sincrónica), o desactivar el botón (asíncrono), o implementar algo del lado del servidor para detectarlo. –

+0

Hola Chris, esto es exactamente lo que he hecho ahora. Inhabilité el botón hasta que la respuesta haya regresado. Gracias de nuevo – CallumVass

1

Puede generar un IssueId cuando muestra el formulario al usuario, luego verifica que no tiene un problema con dicho id en su método Create y, por ejemplo, omita dichas solicitudes.

+0

Bueno, simplemente creará añadir identificadores, ya que IssueId es mi campo PK, por lo que para cada nuevo Issue creado, tendrá un Id nuevo (2, 3, 4, 5, etc.) – CallumVass

2

manera más sencilla que puedo pensar es utilizar la sesión:

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

Lo siento, no uso sesiones como su una aplicación de Autenticación de Windows – CallumVass

+0

@BiffBaffBoff - Comience a usar las variables 'Session'. –

+0

@Biff Las variables de sesión no tienen nada que ver con la autenticación. ¿Qué te hace pensar de esta manera? –

5

solución fácil!

Desactiva el botón de enviar cuando se hace clic. The End.

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

Con esta solución, si el usuario tiene un problema de red entre el clic y la carga de la información en el servidor, entonces no hay forma de salvar la información en el formulario. Si el usuario acaba de pasar 5 minutos completando el formulario, se molestará. Un mejor enfoque es, probablemente, desactivarlo solo hasta que la red tenga éxito o falle. –

+0

Esto no funcionará con JavaScript deshabilitado? –

+0

@AlexAngas, nada funcionará cuando javascript esté deshabilitado. No creo que haya una buena forma de hacerlo sin js. (_Shadow Wizard_ la respuesta a continuación es difícil de codificar 1000 ms, lo que está lejos de ser ideal, ¿y si el usuario tiene una conexión de red lenta?) – gdoron

0

El patrón PRG no evitará esto, ya que la acción P lleva tiempo (que suele ser el caso) y el usuario puede volver a enviar el formulario (mediante clic o actualización del navegador), lo que provocará que el patrón PRG "fallar".

Tenga en cuenta que los usuarios malintencionados también pueden omitir todas las medidas del lado del cliente ejecutando varias publicaciones http en rápida sucesión.

Una solución a todo lo anterior es verificar si hay envíos duplicados en el lado del servidor usando el siguiente método, como lo describí yo mismo, here.

Para su comodidad, cito:

"Si usted hace uso de un token anti-falsificación oculto en su forma (como se debería), se puede almacenar en caché el anti-falsificación ficha en primer lugar presentar y eliminar el token de la memoria caché si es necesario, o caducar con la entrada en caché después de cierta cantidad de tiempo.

a continuación, será capaz de comprobar con cada solicitud en contra de la caché si la forma específica ha sido enviado y lo rechazan si lo tiene ".

Cuestiones relacionadas