Respuesta. ¿Redireccionar con POST en lugar de Obtener?

Resuelto Matt Dawdy asked hace 16 años • 14 respuestas

Tenemos el requisito de enviar un formulario y guardar algunos datos, luego redirigir al usuario a una página externa, pero al redirigir, debemos "enviar" un formulario con POST, no GET.

Esperaba que hubiera una manera fácil de lograr esto, pero estoy empezando a pensar que no la hay. Creo que ahora debo crear otra página simple, solo con el formulario que quiero, redirigir a ella, completar las variables del formulario y luego hacer una llamada body.onload a un script que simplemente llama a document.forms[0].submit( );

¿Alguien puede decirme si hay alguna alternativa? Es posible que necesitemos modificar esto más adelante en el proyecto, y podría volverse un poco complicado, por lo que si fuera fácil, podríamos hacer esto sin depender de ninguna otra página, sería fantástico.

De todos modos, gracias por todas y cada una de las respuestas.

Matt Dawdy avatar Sep 06 '08 02:09 Matt Dawdy
Aceptado

Para hacer esto, es necesario comprender cómo funcionan las redirecciones HTTP. Cuando usas Response.Redirect(), envías una respuesta (al navegador que realizó la solicitud) con el código de estado HTTP 302 , que le indica al navegador adónde ir a continuación. Por definición, el navegador lo hará mediante una GETsolicitud, incluso si la solicitud original era un archivo POST.

Otra opción es utilizar el código de estado HTTP 307 , que especifica que el navegador debe realizar la solicitud de redireccionamiento de la misma manera que la solicitud original, pero para mostrarle al usuario una advertencia de seguridad. Para hacer eso, escribirías algo como esto:

public void PageLoad(object sender, EventArgs e)
{
    // Process the post on your side   
    
    Response.Status = "307 Temporary Redirect";
    Response.AddHeader("Location", "http://example.com/page/to/post.to");
}

Desafortunadamente, esto no siempre funcionará. Los distintos navegadores implementan esto de forma diferente , ya que no es un código de estado común.

Lamentablemente, a diferencia de los desarrolladores de Opera y Firefox, los desarrolladores de IE nunca han leído la especificación, e incluso el IE7 más reciente y seguro redirigirá la solicitud POST del dominio A al dominio B sin advertencias ni cuadros de diálogo de confirmación. Safari también actúa de una manera interesante, si bien no genera un cuadro de diálogo de confirmación y realiza la redirección, descarta los datos POST, cambiando efectivamente la redirección 307 por la más común 302.

Entonces, hasta donde yo sé, la única forma de implementar algo como esto sería usar Javascript. Hay dos opciones que se me ocurren en la cabeza:

  1. Cree el formulario y haga que su actionatributo apunte al servidor de terceros. Luego, agregue un evento de clic al botón de enviar que primero ejecute una solicitud AJAX a su servidor con los datos y luego permita que el formulario se envíe al servidor de terceros.
  2. Cree el formulario para publicar en su servidor. Cuando se envíe el formulario, muéstrele al usuario una página que tenga un formulario con todos los datos que desea transmitir, todo en entradas ocultas. Simplemente muestra un mensaje como "Redireccionando...". Luego, agregue un evento de JavaScript a la página que envía el formulario al servidor de terceros.

De los dos elegiría el segundo, por dos motivos. Primero, es más confiable que el primero porque no se requiere Javascript para que funcione; Para aquellos que no lo tienen habilitado, siempre pueden hacer visible el botón de enviar para el formulario oculto e indicarles que lo presionen si demora más de 5 segundos. En segundo lugar, puede decidir qué datos se transmiten al servidor de terceros; Si usa simplemente procesar el formulario a medida que avanza, pasará todos los datos de la publicación, que no siempre son los que desea. Lo mismo ocurre con la solución 307, suponiendo que funcione para todos sus usuarios.

tghw avatar Sep 06 '2008 18:09 tghw

Puede utilizar este enfoque:

Response.Clear();

StringBuilder sb = new StringBuilder();
sb.Append("<html>");
sb.AppendFormat(@"<body onload='document.forms[""form""].submit()'>");
sb.AppendFormat("<form name='form' action='{0}' method='post'>",postbackUrl);
sb.AppendFormat("<input type='hidden' name='id' value='{0}'>", id);
// Other params go here
sb.Append("</form>");
sb.Append("</body>");
sb.Append("</html>");

Response.Write(sb.ToString());

Response.End();

Como resultado, justo después de que el cliente obtenga todo el HTML del servidor, se produce la carga del evento que activa el envío del formulario y publica todos los datos en la URL de devolución de datos definida.

Pavlo Neiman avatar May 10 '2010 13:05 Pavlo Neiman

Para ello se utiliza HttpWebRequest.

En la devolución de datos, cree una HttpWebRequest para su tercero y publique los datos del formulario, luego, una vez hecho esto, puede Response.Redirect donde desee.

Obtiene la ventaja adicional de que no tiene que nombrar todos los controles de su servidor para crear el formulario de terceros; puede hacer esta traducción al crear la cadena POST.

string url = "3rd Party Url";

StringBuilder postData = new StringBuilder();

postData.Append("first_name=" + HttpUtility.UrlEncode(txtFirstName.Text) + "&");
postData.Append("last_name=" + HttpUtility.UrlEncode(txtLastName.Text));

//ETC for all Form Elements

// Now to Send Data.
StreamWriter writer = null;

HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";                        
request.ContentLength = postData.ToString().Length;
try
{
    writer = new StreamWriter(request.GetRequestStream());
    writer.Write(postData.ToString());
}
finally
{
    if (writer != null)
        writer.Close();
}

Response.Redirect("NewPage");

Sin embargo, si necesita que el usuario vea la página de respuesta de este formulario, su única opción es utilizar Server.Transfer, y eso puede funcionar o no.

FlySwat avatar Sep 05 '2008 19:09 FlySwat

Esto debería hacer la vida mucho más fácil. Simplemente puede utilizar el método Response.RedirectWithData(...) en su aplicación web fácilmente.

Imports System.Web
Imports System.Runtime.CompilerServices

Module WebExtensions

    <Extension()> _
    Public Sub RedirectWithData(ByRef aThis As HttpResponse, ByVal aDestination As String, _
                                ByVal aData As NameValueCollection)
        aThis.Clear()
        Dim sb As StringBuilder = New StringBuilder()

        sb.Append("<html>")
        sb.AppendFormat("<body onload='document.forms[""form""].submit()'>")
        sb.AppendFormat("<form name='form' action='{0}' method='post'>", aDestination)

        For Each key As String In aData
            sb.AppendFormat("<input type='hidden' name='{0}' value='{1}' />", key, aData(key))
        Next

        sb.Append("</form>")
        sb.Append("</body>")
        sb.Append("</html>")

        aThis.Write(sb.ToString())

        aThis.End()
    End Sub

End Module
ZooZ avatar Aug 29 '2012 09:08 ZooZ