El patrón Post-Redirect-Get

Hoy vamos a dedicar un rato a comentar una técnica que es considerada una buena práctica en el desarrollo de aplicaciones web: el patrón PRG o Post-Redirect-Get. Seguramente alguna vez lo haya citado por aquí, pero nunca lo había explicado en profundidad.

Por último, antes de entrar en materia, es conveniente indicar que lo que vamos a ver es válido para ASP.NET Webforms, ASP.NET MVC y, en general, para cualquier tecnología de construcción de sitios web que incluya componentes en servidor, puesto que se trata de una forma de hacer las cosas, no de la implementación de una solución. Ya en el último epígrafe veremos implementaciones concretas para Webforms y el framework MVC.

El problema

Es bastante habitual que al desarrollar aplicaciones para la web creemos un formulario de introducción de datos, y lo normal es que estos envíen los datos al servidor utilizando el verbo HTTP Post. Hasta aquí, bien.

Cuando desde el servidor se recibe una petición de este tipo normalmente se ejecuta un código, por ejemplo para almacenar la información en la base de datos y, de forma bastante frecuente, aprovechamos para enviar al cliente feedback de que su operación ha sido realizada con éxito. Y aquí es donde aparece el problema.

image Si el usuario, por esas ocurrencias que suele tener ;-), decide pulsar F5 o actualizar la página en el navegador, se van a producir dos efectos desagradables:

  • primero, se le mostrará al usuario un cuadro de diálogo informándolo de algo que difícilmente va a entender y que, en cualquier caso, le asustará bastante. El navegador le informa de que está realizando un reenvío completo de los datos del formulario.
  • segundo, una vez superado el escollo anterior, se volvería a ejecutar en servidor toda la lógica asociada a la recepción de datos del formulario con consecuencias, a veces terribles, como el almacenamiento de registros duplicados en la base de datos.

¿Cómo podemos evitar esto?

La solución: Post-Redirect-Get

El patrón PRG viene a indicarnos una forma de diseñar nuestras aplicaciones pensando en evitar los problemas descritos anteriormente, y, como veremos, es bastante simple. El procedimiento general a seguir sería:

  1. Recibimos la petición Post con los datos que ha introducido el usuario en un formulario.
  2. Ejecutamos la lógica asociada a la recepción de dicho formulario, por ejemplo, grabar en la base de datos.
  3. Enviamos al cliente una respuesta con código HTTP 30x (Redirect), indicando al agente de usuario que debe solicitar otra página, en la mostraremos un mensaje informando de que el proceso se ha realizado con éxito.
  4. El navegador obtiene dicha página mediante una petición de tipo Get.

En este punto, si el usuario decide (o el diablo que lleva dentro le ordena ;-)) refrescar la página, lo único que conseguirá será que su navegador vuelva a solicitar la página en la que le estamos informando de que el proceso ha sido satisfactorio. No se le muestra ningún cuadro de diálogo amenazante, ni se ejecuta la lógica de nuevo, ni hay ningún tipo de daños colaterales.

El siguiente diagrama, basado en el de la imprescindible Wikipedia, muestra gráficamente este proceso:

Secuencia en el patrón PRG

¿Un poco de código? Sí, por favor

ASP.NET WebForms

La abstracción sobre los protocolos montada por la tecnología Webforms hace más difícil reconocer los conceptos que estamos tratando, pero aún así es bastante sencillo aplicar el patrón.

En los formularios web, los postbacks se realizan a través de métodos Http POST, por lo que la implementación de la lógica y la redirección podremos realizarlas en la implementación del evento de servidor correspondiente, por ejemplo, el de pulsación de un botón:

protected void btnAceptar_Click(object sender, EventArgs e)

{

    if (Page.IsValid)

    {

        // Lógica 

        Cliente cliente = new Cliente(txtNombre.Text, txtApellidos.Text);

        GestorDeClientes.Salvar(cliente);

    

        // Redirección

        Response.Redirect("clientes.aspx", true);

    }

}

 

La página “clientes.aspx” podría ser ser el listado de clientes registrados en el sistema, por ejemplo.

ASP.NET MVC

En el framework MVC, por su cercanía a los protocolos, sí es fácil identificar los conceptos de petición y redirecciones. El siguiente código sería equivalente al anteriormente mostrado, pero enviando al usuario a la acción “Index”:

[HandleError]

public class ClientesController : Controller

{

    ... // Otras acciones

 

    [AcceptVerbs(HttpVerbs.Post)]

    public ActionResult Editar(Cliente cliente)

    {

        if (ModelState.IsValid)

        {

            GestorDeClientes.Grabar(cliente);

            return RedirectToAction("Index");

        }

        return View(cliente);

    }

}

Crossposteando desde: El patrón Post-Redirect-Get.

Un comentario sobre “El patrón Post-Redirect-Get”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *