Response.Redirect con POST en lugar de Get?

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

Esperaba que hubiera una manera fácil de lograr esto, pero estoy empezando a pensar que no. Creo que ahora debo crear una página sencilla, con la forma que quiero, redirigir a ella, rellenar las variables de formulario y luego hacer una llamada body.onload a una secuencia de comandos que simplemente llama a document.forms [0] .submit ( );

¿Alguien puede decirme si hay una alternativa? Es posible que tengamos que modificar esto más adelante en el proyecto, y podría ser algo complicado, por lo que si fuera fácil podríamos hacer esto dependiendo de la otra página que fuera fantástica.

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

    Hacer esto requiere comprender cómo funcionan los redireccionamientos HTTP. Cuando usa Response.Redirect() , envía una respuesta (al navegador que realizó la solicitud) con el código de estado HTTP 302 , que le dice al navegador a dónde irá. Por definición, el navegador hará eso a través de una solicitud GET , incluso si la solicitud original fue un 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 avisar al usuario de 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 diferentes navegadores implementan esto de manera diferente , ya que no es un código de estado común.

    Desafortunadamente, a diferencia de los desarrolladores de Opera y FireFox, los desarrolladores de IE nunca han leído las especificaciones, e incluso el último IE7 más seguro redirigirá la solicitud POST del dominio A al dominio B sin advertencias ni diálogos de confirmación. Safari también actúa de una manera interesante, mientras que no genera un diálogo de confirmación y realiza la redirección, descarta los datos POST, cambiando efectivamente la 307 redirección a la 302 más común.

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

    1. Cree el formulario y haga que su atributo de action apunte al servidor de terceros. Luego, agregue un evento de clic al botón de enviar que primero ejecuta una solicitud de AJAX a su servidor con los datos, y luego permite que el formulario se envíe al servidor de terceros.
    2. Crea el formulario para publicar en tu servidor. Cuando se envía el formulario, muestre al usuario una página que tiene un formulario con todos los datos que desea transmitir, todo en entradas ocultas. Solo muestre un mensaje como “Redirigir …”. A continuación, 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 razones. Primero, es más confiable que el primero porque no se requiere Javascript para que funcione; para aquellos que no lo tienen habilitado, siempre puede hacer que el botón de enviar para el formulario oculto sea visible e indicarles que lo presionen si tarda más de 5 segundos. En segundo lugar, puede decidir qué datos se transmiten al servidor de terceros; Si utiliza simplemente procesar el formulario a medida que avanza, pasará todos los datos de la publicación, que no siempre es lo que desea. Lo mismo para la solución 307, suponiendo que funcionó para todos sus usuarios.

    ¡Espero que esto ayude!

    Puedes usar este enfoque:

     Response.Clear(); StringBuilder sb = new StringBuilder(); sb.Append(""); sb.AppendFormat(@""); sb.AppendFormat("
    ",postbackUrl); sb.AppendFormat("", id); // Other params go here sb.Append("
    "); sb.Append(""); sb.Append(""); Response.Write(sb.ToString()); Response.End();

    Como resultado, justo después de que el cliente obtenga todo el html del servidor, tiene lugar la carga del evento que activa el envío y publicación de todos los datos en postbackUrl definido.

    HttpWebRequest se usa para esto.

    En la devolución de datos, cree una HttpWebRequest a su tercero y publique los datos del formulario; una vez hecho esto, puede Response.Redirect donde lo 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 comstackr 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 respuestas de este formulario, su única opción es utilizar Server.Transfer, y eso puede funcionar o no.

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

     Imports System.Web Imports System.Runtime.CompilerServices Module WebExtensions  _ 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("") sb.AppendFormat("") sb.AppendFormat("
    ", aDestination) For Each key As String In aData sb.AppendFormat("", key, aData(key)) Next sb.Append("
    ") sb.Append("") sb.Append("") aThis.Write(sb.ToString()) aThis.End() End Sub End Module

    Algo nuevo en ASP.Net 3.5 es esta propiedad “PostBackUrl” de los botones ASP. Puede configurarlo en la dirección de la página en la que desea publicar directamente, y cuando se hace clic en ese botón, en lugar de volver a publicar en la misma página como lo hace normalmente, se publica en la página que ha indicado. Práctico. Asegúrese de que UseSubmitBehavior también esté establecido en TRUE.

    Pensé que sería interesante compartir que heroku hace esto con su SSO a los proveedores de complementos

    Un ejemplo de cómo funciona se puede ver en la fuente de la herramienta “kensa”:

    https://github.com/heroku/kensa/blob/d4a56d50dcbebc2d26a4950081acda988937ee10/lib/heroku/kensa/post_proxy.rb

    Y se puede ver en la práctica si cambias de javascript. Fuente de página de ejemplo:

     < !DOCTYPE HTML>    Heroku Add-ons SSO   

    PostbackUrl se puede configurar en su botón asp para publicar en una página diferente.

    si necesita hacerlo en código subyacente, intente Server.Transfer.

    @Mate,

    Aún puede usar HttpWebRequest y luego dirigir la respuesta que recibe a la respuesta de salida real, esto le devolverá la respuesta al usuario. El único problema es que cualquier URL relativa se rompería.

    Aún así, eso puede funcionar.

    Esto es lo que haría:

    Coloque los datos en un formulario estándar (sin el atributo runat = “server”) y establezca la acción del formulario para publicar en la página de destino fuera del sitio. Antes de enviarlo, enviaría los datos a mi servidor usando un XmlHttpRequest y analizaría la respuesta. Si la respuesta significa que debe continuar con la POSTing fuera del sitio, entonces yo (el JavaScript) procedería con la publicación; de lo contrario, redirigiría a una página de mi sitio.

    En PHP, puede enviar datos POST con cURL. ¿Hay algo comparable para .NET?

    Sí, HttpWebRequest, mira mi publicación a continuación.

    Sugiero construir una HttpWebRequest para ejecutar programáticamente su POST y luego redirigir después de leer la respuesta si corresponde.

    El método GET (y HEAD) nunca debe usarse para hacer nada que tenga efectos secundarios. Un efecto secundario podría ser actualizar el estado de una aplicación web, o podría estar cargando su tarjeta de crédito. Si una acción tiene efectos secundarios, se debe usar otro método (POST) en su lugar.

    Por lo tanto, un usuario (o su navegador) no debería ser responsable de algo hecho por un GET. Si se produce algún efecto secundario dañino o costoso como resultado de un GET, eso sería culpa de la aplicación web, no del usuario. De acuerdo con la especificación, un agente de usuario no debe seguir automáticamente una redirección a menos que sea una respuesta a una solicitud GET o HEAD.

    Por supuesto, muchas solicitudes GET tienen algunos efectos secundarios, incluso si solo se anexan a un archivo de registro. Lo importante es que la aplicación, no el usuario, debería ser considerada responsable de esos efectos.

    Las secciones relevantes de la especificación HTTP son 9.1.1 y 9.1.2 , y 10.3 .

    Por lo general, todo lo que necesitará es llevar algún estado entre estas dos solicitudes. En realidad, hay una forma realmente funky de hacer esto que no depende de JavaScript (piense en ).

     Set-Cookie: name=value; Max-Age=120; Path=/redirect.html 

    Con esa cookie allí, puede en la siguiente solicitud para /redirect.html recuperar el nombre = información de valor, puede almacenar cualquier tipo de información en este par de nombre / valor, hasta 4K de datos (límite de cookie típico). Por supuesto, debe evitar esto y almacenar códigos de estado y bits de indicadores en su lugar.

    Al recibir esta solicitud, usted responderá con una solicitud de eliminación para ese código de estado.

     Set-Cookie: name=value; Max-Age=0; Path=/redirect.html 

    Mi HTTP está un poco oxidado He estado yendo a través de RFC2109 y RFC2965 para ver qué tan confiable es esto, preferiblemente me gustaría que la cookie hiciera un viaje de ida y vuelta exactamente una vez, pero eso no parece posible, también, las cookies de terceros podría ser un problema para usted si se está mudando a otro dominio. Esto todavía es posible pero no tan sencillo como cuando haces cosas dentro de tu propio dominio.

    El problema aquí es la concurrencia, si un usuario avanzado usa varias tabs y logra intercalar un par de solicitudes que pertenecen a la misma sesión (esto es muy poco probable, pero no imposible), esto puede generar inconsistencias en su aplicación.

    Es la forma de hacer viajes de ida y vuelta HTTP sin URLs sin sentido y JavaScript

    Proporciono este código como profador de concepto: si este código se ejecuta en un contexto con el que no está familiarizado, creo que puede averiguar qué parte es qué.

    La idea es que llame a Reubicarse con algún estado cuando lo redirija, y la URL que reubicó llamará a GetState para obtener los datos (si los hay).

     const string StateCookieName = "state"; static int StateCookieID; protected void Relocate(string url, object state) { var key = "__" + StateCookieName + Interlocked .Add(ref StateCookieID, 1).ToInvariantString(); var absoluteExpiration = DateTime.Now .Add(new TimeSpan(120 * TimeSpan.TicksPerSecond)); Context.Cache.Insert(key, state, null, absoluteExpiration, Cache.NoSlidingExpiration); var path = Context.Response.ApplyAppPathModifier(url); Context.Response.Cookies .Add(new HttpCookie(StateCookieName, key) { Path = path, Expires = absoluteExpiration }); Context.Response.Redirect(path, false); } protected TData GetState() where TData : class { var cookie = Context.Request.Cookies[StateCookieName]; if (cookie != null) { var key = cookie.Value; if (key.IsNonEmpty()) { var obj = Context.Cache.Remove(key); Context.Response.Cookies .Add(new HttpCookie(StateCookieName) { Path = cookie.Path, Expires = new DateTime(1970, 1, 1) }); return obj as TData; } } return null; }