Pregunta

¿Cómo puedo implementar el Post-redirección Patrón con ASP.NET?

Un clic de botón realiza algún procesamiento:

<asp:Button id="bbLaunch" OnCommand="bbLaunch_Click" />

El usuario hace clic en el botón, se inicia la nave espacial, la página web se vuelve a probar. Si el usuario presiona F5, obtiene la advertencia:

enter image description here

La solución al problema es el Post-redirección patrón.

¿Cuál es el método por el cual PRG ¿Se puede implementar en ASP.NET?


La pregunta se centra en los problemas de:

  • ¿Cómo puede el <asp:Button> realizar POST ¿A un lugar que no sea su forma original?
  • lo que se convierte en el Viewstate ¿Cuando publica un formulario que no lee el estado de la vista?
  • lo que se convierte en el Viewstate ¿Cuando redirige al formulario web ASPX "real"?
  • es Viewstate fundamentalmente incompatible con ASP.NET ¿Post-Redirect-get?
  • ASP.NET es fundamentalmente incompatible con Post-redirección-get?
  • cómo (es decir, ¿qué código) redirige al formulario web ASPX "real"?
  • cómo (es decir, ¿qué URL) Redirige a la forma web ASPX "real"? Una cuestión de relación menciona Response.Redirect(Request.RawUrl);
  • cuando (es decir, en qué manejador de eventos) ¿Redirige al formulario web ASPX "real"?
  • Las preguntas relacionadas plantean problemas de cómo publicas datos de formulario. Existe la implicación de que html formularios no se puede utilizar, y todos los datos de formulario deben agregarse a la cadena de consulta. ¿Es esto cierto? Si es así, ¿por qué? ¿Si no, porque no? Pueden ¿Un navegador pone datos de formulario en una cadena de consulta?
  • Una pregunta relacionada menciona Server.Transfer. Usando Server.Transfer está completamente equivocado, y de ninguna manera resuelve el problema posterior a la redirección (porque no hay Redireccionar). ¿Correcto?
  • ¿Qué cambio de código tiene que suceder en el aspx o aspx.cs archivo para admitir PRG? Presumiblemente, al menos, el código debe cambiarse a post en algún lugar además MyPage.aspx.

En otras palabras: ¿Cómo se hace post-redirect-get en asp.net?

Nota: ASP.NET (es decir, no ASP.NET MVC)

Ver también

¿Fue útil?

Solución

Por lo general, lo haría haciendo un formulario web ASPX que use la QueryString para indicar qué registro se cargará/procesa.

Supongamos que tiene una página que le permite actualizar alguna información del cliente:

http://www.mysite.com/customer.aspx

Cargaría el formulario usando una ID en la Querystring:

http://www.mysite.com/customer.aspx?CustomerId=42

En el CodeBehind tendrías algo como esto:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        int customerId = 0;
        if (!string.IsNullOrEmpty(Request.QueryString["CustomerId"]))
        {
            int.TryParse(Request.QueryString["CustomerId"], out customerId );
        }
        if (customerId == 0) 
        {
            //handle case when no valid customer id was passed in the qs here
        }
        else 
        {
            //load customer details, bind controls etc
            //make sure to handle the case when no customer was found using the id in the qs
        }
    }
}

Luego, en algún lugar de su página, tendrá un botón que guarde los cambios. Ese botón tendría un controlador de entrada en el código detrás:

protected void SaveClicked(object sender, EventArgs e)
{
    //save changes to database here

    //Redirect if all went well
    Response.Redirect("http://www.mysite.com/customer.aspx?CustomerId=" 
        + idOfSavedCustomer.ToString());
}

Eso debería ser básicamente todo. La redirección hará que el navegador emita una nueva solicitud GET para la URL en la redirección (...). Cargará la página, el if (!IsPostBack) Se ejecutará e inicializará la página con los nuevos valores que acaba de guardar en la publicación anterior.

Para todo este proceso, el tráfico entre el navegador y el servidor se vería algo así:

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send back some html)

Browser: POST http://www.mysite.com/customer.aspx?CustomerId=42 (post data sent in request)
Server: 302 (point to http://www.mysite.com/customer.aspx?CustomerId=42)

Browser: GET http://www.mysite.com/customer.aspx?CustomerId=42
Server: 200 (send html)

En el paso medio, el servidor básicamente dice:

"Esa solicitud de publicación que me enviaste, he terminado con eso. Ahora, por favor, llegué a esta otra página aquí ..."

El hecho de que la URL de hecho se refería a la misma página no es importante.


Algunas reflexiones en respuesta a su lista de preguntas de Bullet Point:

  • ¿Cómo puede realizar una publicación en un lugar que no sea su forma original?

Puedes hacer esto configurando el action atributo en el formulario, o puede establecer el PostBackUrl en el botón.

  • ¿Qué pasa con ViewState cuando publica un formulario que no lee el estado de la vista?

Depende. Si simplemente publica el formulario en una página diferente, puede usar la directiva <%@ anteriorpageType .../> para decir la página "nueva" de la que proviene la publicación. Esto simplemente trabajará con los datos publicados en la nueva página. Ver este enlace para más detalles.

  • ¿Qué pasa con ViewState cuando redirige a la forma web ASPX "real"?

View State se envía en la solicitud posterior. Al redirigir, el navegador cargará una nueva página y creará su propio viesterate.

  • ¿ViewState es fundamentalmente incompatible con ASP.NET post-redirect-get?

Depende de cómo lo mires. Después de la redirección, la nueva página no tendrá acceso a ViewState de la página anterior.

  • ¿ASP.NET es fundamentalmente incompatible con la redirección post-redirección?

No. Vea el ejemplo anterior.

  • ¿Cómo (es decir, qué código) redirige al formulario web ASPX "real"?

Respuesta. Redirect (URL). Esto enviará una respuesta al navegador, diciéndole que haga una nueva solicitud GET.

  • ¿Cuándo (es decir, qué manejador de eventos) redirige a la forma web ASPX "real"?

Cuando haya realizado todo el trabajo necesario para procesar la solicitud posterior.

  • Las preguntas relacionadas plantean problemas de cómo publica los datos del formulario. Existe la implicación de que no se pueden usar los formularios HTML, y todos los datos de formulario deben agregarse a la cadena de consulta. ¿Es esto cierto? Si es así, ¿por qué? ¿Si no, porque no? ¿Puede un navegador poner los datos de formulario en una cadena de consulta?

La redireccionamiento de una solicitud de publicación no es bien compatible y probablemente debe evitarse. Se puede hacer (con un navegador) utilizando la respuesta HTTP 307. Al hacerlo, el servidor efectivamente le dice al navegador que "No procesaré su solicitud de publicación, publíquela en esta otra página en su lugar".

  • Una pregunta relacionada menciona server.transfer. El uso de server.transfer es completamente incorrecto, y de ninguna manera resuelve el problema posterior a la redirección (porque no hay redirección). ¿Correcto?

Server.Transfer (...) es algo que está teniendo lugar en el lado del servidor. El navegador no es consciente de ello. Básicamente, una página puede usar servidor. Transferir para que alguna otra página realice algún procesamiento, y esa página será responsable de enviar una respuesta al navegador. Pero el navegador pensará que fue la página original que respondió.

  • ¿Qué cambio de código debe suceder en el archivo ASPX o ASPX.CS para admitir PRG? Presumiblemente, al menos, el código debe cambiarse para publicar en algún lugar además de mypage.aspx.

No, se puede usar una publicación regular. El truco es tener uno (o algunos) manejadores de eventos específicos en la página que realiza un RepSonse.Redirect después de procesar los datos publicados.

Otros consejos

P) ¿Cómo puede realizar una publicación en un lugar que no sea su forma original?

A) Con PRG, no publica una página diferente, publica la misma página (consulte el diagrama en la página de Wikipedia a la que se vinculó). Pero la respuesta de esa página debe ser una respuesta de 30x (generalmente un 302 .)

P) ¿Qué se convierte en ViewState cuando publica un formulario que no lee el estado de la vista?

A) El estado de vista está allí cuando publica, pero allí el estado de vista no estará allí para la nueva página en la que está haciendo.

P) ¿Qué se convierte en ViewState cuando redirige a la forma web ASPX "real"?

A) Según arriba, no hay más estado de vista, redirigiendo a la página.

P) ¿ViewState es fundamentalmente incompatible con ASP.NET?

A) ViewState no es incompatible con ASP.NET. Es (principalmente) inútil para P/R/G para hacer que la página sea redirigida.

P) ¿ASP.NET es fundamentalmente incompatible con post-redirección?

A) No, pero no puede confiar demasiado en usar una página y mantener todo su estado en ViewState, según lo anterior. Dicho esto, ASP.MVC es mucho mejor para P/R/G

P) ¿Cómo (es decir, qué código) redirige al formulario web ASPX "real"?

A) Response.Redirect ("new_page_you_are_redirecting_to.aspx") en el método bblaunch_click de Old_Page_You_are_Posting_From.aspx

P) ¿Cómo (es decir, qué URL) redirige a la forma web ASPX "real"? Una pregunta de relación menciona la respuesta. Redirect (request.rawurl);

A) Ver arriba

P) ¿Cuándo (es decir, en qué manejador de eventos) redirige al formulario web ASPX "real"?

A) Después de procesar el botón, presione, guardó los datos en DB (o sesión, etc.), y antes de haber escrito cualquier otra cosa en el flujo de respuesta.

P) Las preguntas relacionadas plantean problemas de cómo publica los datos del formulario. Existe la implicación de que no se pueden usar los formularios HTML, y todos los datos de formulario deben agregarse a la cadena de consulta. ¿Es esto cierto?

A) No: el botón presiona en ASP.NET WebForms publicará nuevamente en la página.

P) Si es así, ¿por qué? ¿Si no, porque no?

A) Es más simple que esto, es por qué no. Imágenes Dos páginas: First_Page.asp y Second_Page.aspx. First_Page.aspx tiene el botón (junto con otros controles web de ASP.NET, como cuadros de texto, etc. que el usuario ha completado). Cuando presione el botón, se realiza una publicación en First_Page.aspx. Después de procesar los datos (que probablemente esté dentro de ViewState, aunque esto se abstrae), redirige al usuario a Second_Page.aspx usando Response.Redirect. Second_page.aspx puede mostrar lo que desea. Si desea (o necesita) mostrar una interfaz de usuario similar a lo que estaba en First_Page.aspx, incluidos los controles y lo que ingresaron, querrá almacenarlo en la sesión, una cookie, la URL como parámetros de consulta, para establecer Esos controles en Second_Page.aspx. (Pero es posible que no necesite mostrar nada en Second_Page.aspx que sea similar a First_Page.aspx, por lo que no hay una regla general aquí).

P) ¿Puede un navegador colocar datos de formulario en una cadena de consulta?

A) Sí, si establece el método para obtener en lugar de POST. No puede anular las formas web para hacer esto, y esto no es necesario para PRG

P) Una pregunta relacionada menciona server.transfer. El uso de server.transfer es completamente incorrecto, y de ninguna manera resuelve el problema posterior a la redirección (porque no hay redirección). ¿Correcto?

A) esencialmente

P) ¿Qué cambio de código debe suceder en el archivo ASPX o ASPX.CS para admitir PRG? Presumiblemente, al menos, el código debe cambiarse para publicar en algún lugar además de mypage.aspx.

A) El código aún debe publicar (como se mencionó anteriormente). Pero luego myPage.aspx debe volver a dirigir a una nueva página en el controlador de botones.

El patrón posterior a la redirección se puede usar en formularios web. He demostrado cómo se puede hacer esto convirtiendo la aplicación MVC NerdDinner en formularios web, http://navigationnerddinner.codeplex.com/ . He mantenido los detalles de navegación exactamente iguales, por lo que hay muchos ejemplos del patrón PRG.

Sin embargo, hay otra forma de evitar el problema de F5/Actualización. Si envuelve su página en un UpdatePanel (parte de ASP.NET AJAX), todas las publicaciones se convertirán en solicitudes de página parciales. Esto significa que cuando se presiona F5 solo actualizará la solicitud TET original (ya que no ha habido ninguna publicación posterior), por lo que no obtendrá la advertencia. (Tenga en cuenta que si JavaScript está deshabilitado, la advertencia aún aparecerá).

Los pasos exactamente de la obtención de redireccionamiento son este:

Tiene el formulario que completa con datos, y después de su envío válido (publicar), los inserta en su base de datos y les da una ID de confirmación, luego redirige al usuario a la página con este ID de confirmación como parámetro URL que se utiliza A medida que (se obtenga) después de la redirección, cada refresh F5 solo se lee los datos y no los inserte nuevamente.

El código para insertar es diferente al código que muestra la confirmación, incluso puede hacerlas diferentes páginas: puede hacer la misma página con cuadros de texto solo de lectura.

La redirección es simple la Responce.Redirect función de ASP.NET

Después de la publicación y la realización de la redirección, el único pensamiento que lo conecta con la acción anterior es el código de confirmación (no el ViewState)

El menos de este método es que en realidad no es reconocer la actualización, es solo dar un paso adicional que hace que la actualización no inserte nuevamente los mismos datos, pero necesita código adicional para obtener datos.

La alternativa es reconocer la actualización y no redirigir. Al reconocer la actualización de la publicación, puede evitar insertar los mismos datos con un solo mensaje al usuario. Hay algunos ejemplos en Internet para eso, y he implementado uno con éxito.

Un ejemplo: http://www.codeproject.com/tips/319955/how-to-prevent-re-post-action-caused-by-pressing-B

Puedes invocar el Respuesta. Redirección Método para ir a otra ubicación.

Hay un par de cosas que entran en esto.

  1. Selecciona el acción atributo del formulario en la página principal (llamémoslo LaunchForm.aspx) igual a la URL de la página "proxy" (Proxylaunchform.aspx).

    u003Cform id="form1" runat="server" action="ProxyLaunchForm.aspx" method="POST">

  2. (opcional) Agregue una entrada oculta con el nombre Redireccionar URL a la forma y valora la URL que indica Proxylaunchform.aspx dónde redirigir una vez que termine de realizar el lanzamiento (la parte R de PRG).

  3. Ahora Proxylaunchform.aspx, la implementación debe tener lugar dentro del Page_load Manejador de eventos, porque eso tiene acceso a los datos posteriores a la publicación. Ejecute el lanzamiento aquí.

  4. Posteriormente (también en Page_load), realice la redirección (ya sea usando el Redireccionar URL Desde #2, o simplemente usando la URL de la página de referencia):

    Respuesta.Redirect (request.Params ["redirecturl"] ?? request.urlreferrer.absoluteuri);

    Todavía está el asunto del estado de vista. Creo que la forma más fácil de lidiar con esto es cambiar la forma en que persiste el estado de vista. Normalmente, se guarda en un elemento de entrada oculto en la página y se recupera en la respuesta (lo que por supuesto significa que se perdería después de la redirección debido a la naturaleza sin estado de HTTP). Sin embargo, puede anular los métodos que usa ASP.NET y hacer que use el Sesión En cambio (de esa manera todavía estará presente incluso después de la acción de proxy PRG). Así que finalmente...

  5. En LaunchForm.aspx.cs, use como la clase base subclasiada Página que anula el SavePageStatePersistencemedium y LoadPagestatefrompersistencemedium Métodos para almacenarlos/recuperarlos de la sesión, en lugar de desde un campo de forma oculta. Ver a continuación (y Aquí hay más información sobre cómo funciona esto.).

*

public class PersistViewStateToSession : Page
{
    protected override void SavePageStateToPersistenceMedium(object viewState)
    {
        // serialize the view state into a base-64 encoded string
        LosFormatter los = new LosFormatter();
        StringWriter writer = new StringWriter();
        los.Serialize(writer, viewState);
        // save the string to session
        Session["LaunchViewState"] = writer.ToString();
    }

    protected override object LoadPageStateFromPersistenceMedium()
    {
       if (!Session["LaunchViewState"] == null)
           return null;
       else
       {
          string sessionString = (string)Session["LaunchViewState"];
          // deserialize the string
          LosFormatter los = new LosFormatter();
          return los.Deserialize(viewStateString);
       }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top