asp.net - redirect post c#
Response.Redirect con POST en lugar de Get? (13)
En PHP, puede enviar datos POST con cURL. ¿Hay algo comparable para .NET?
Sí, HttpWebRequest, vea mi publicación a continuación.
Tenemos el requisito de enviar un formulario y guardar algunos datos, luego redirigir al usuario a una página fuera del sitio, pero al redireccionar, debemos "enviar" un formulario con POST, no con GET.
Esperaba que hubiera una manera fácil de lograr esto, pero estoy empezando a pensar que no lo hay. Creo que ahora debo crear otra página simple, con solo el formulario que quiero, redirigirlo, llenar las variables del formulario, y luego hacer una llamada de body.onload a un script que simplemente llame 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 complicarse un poco, por lo que si hubiera una manera fácil podríamos hacer esto sin depender de ninguna otra página, eso sería fantástico.
De todos modos, gracias por cualquier y todas las respuestas.
@Mate,
Aún puede usar HttpWebRequest y luego dirigir la respuesta que recibe a la respuesta real de la salida, esto devolvería la respuesta al usuario. El único problema es que cualquier URL relativa se rompería.
Aún así, eso puede funcionar.
Algo nuevo en ASP.Net 3.5 es esta propiedad "PostBackUrl" de los botones ASP. Puede configurarlo a 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.
El método GET (y HEAD) nunca debe usarse para hacer nada que tenga efectos secundarios. Un efecto colateral puede ser la actualización del estado de una aplicación web o la carga de su tarjeta de crédito. Si una acción tiene efectos secundarios, se debe utilizar otro método (POST).
Por lo tanto, un usuario (o su navegador) no debe ser responsabilizado por algo hecho por un GET. Si ocurriera 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. Según 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 están agregando a un archivo de registro. Lo importante es que la aplicación, no el usuario, debe ser responsable de esos efectos.
Las secciones relevantes de la especificación HTTP son 9.1.1 y 9.1.2 , y 10.3 .
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
<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
Esto es lo que yo haría:
Coloque los datos en un formulario estándar (sin el atributo runat = "servidor") y configure la acción del formulario para que se publique en la página de destino externa. Antes de enviar, enviaría los datos a mi servidor utilizando un XmlHttpRequest y analizaría la respuesta. Si la respuesta significa que debe seguir adelante con el POSTing externo, entonces I (el JavaScript) continuaría con la publicación; de lo contrario, redirigiría a una página de mi sitio.
Pensé que podría ser interesante compartir que heroku hace esto con su SSO para proveedores de complementos
Un ejemplo de cómo funciona puede verse en la fuente de la herramienta "kensa":
Y se puede ver en la práctica si apagas de javascript. Ejemplo de fuente de página:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Heroku Add-ons SSO</title>
</head>
<body>
<form method="POST" action="https://XXXXXXXX/sso/login">
<input type="hidden" name="email" value="XXXXXXXX" />
<input type="hidden" name="app" value="XXXXXXXXXX" />
<input type="hidden" name="id" value="XXXXXXXX" />
<input type="hidden" name="timestamp" value="1382728968" />
<input type="hidden" name="token" value="XXXXXXX" />
<input type="hidden" name="nav-data" value="XXXXXXXXX" />
</form>
<script type="text/javascript">
document.forms[0].submit();
</script>
</body>
</html>
Por lo general, todo lo que necesitará es llevar un estado entre estas dos solicitudes. En realidad, hay una forma realmente extraña de hacerlo que no se basa en JavaScript (piense en <noscript />).
Set-Cookie: name=value; Max-Age=120; Path=/redirect.html
Con esa cookie allí, en la siguiente solicitud para /redirect.html recuperar la información de name = value, puede almacenar cualquier tipo de información en esta cadena de par de nombre / valor, hasta 4K de datos (límite típico de cookie). Por supuesto, debe evitar esto y almacenar códigos de estado y bits de marca en su lugar.
Al recibir esta solicitud, a cambio responde 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 revisando el RFC2109 y el RFC2965 para averiguar qué tan confiable es esto, de preferencia querría que la cookie saliera exactamente una vez, pero eso no parece ser posible, también, cookies de terceros. podría ser un problema para usted si se está reubicando en otro dominio. Esto todavía es posible pero no tan indoloro como cuando estás haciendo cosas dentro de tu propio dominio.
El problema aquí es la concurrencia, si un usuario avanzado está usando varias pestañas y logra intercalar un par de solicitudes que pertenecen a la misma sesión (esto es muy improbable, pero no imposible), esto puede dar lugar a inconsistencias en su aplicación.
Es la forma <noscript /> de hacer viajes de ida y vuelta en HTTP sin URL y JavaScript sin sentido.
Ofrezco este código como concepto de concepto: si este código se ejecuta en un contexto con el que no está familiarizado, creo que puede determinar qué parte es qué.
La idea es que llame a Relocate con cierto estado cuando redirija, y la URL que reubicó llama a GetState para obtener los datos (si los hubiera).
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<TData>()
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;
}
PostbackUrl puede configurarse en su botón de asp para publicar en una página diferente.
Si necesita hacerlo en codebehind, intente Server.Transfer.
Puedes usar 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 todos los html del servidor, se llevará a cabo el evento onload que activa el envío del formulario y publica todos los datos en postbackUrl definido.
Se utiliza HttpWebRequest para esto.
En la devolución de datos, cree un HttpWebRequest a su tercero y publique los datos del formulario, luego, una vez hecho esto, puede Response.Redirect donde lo desee.
Obtiene la ventaja adicional de que no tiene que nombrar a todos los controles de su servidor para hacer que se formen los 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 o no funcionar.
Sugiero crear un HttpWebRequest para ejecutar su POST mediante programación y luego redirigir después de leer la Respuesta, si corresponde.
Hacer esto requiere entender 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 indica al navegador dónde debe ir a continuación. Por definición, el navegador lo hará a través de una solicitud GET
, incluso si la solicitud original era un POST
.
Otra opción es usar 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 con 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 funciona. Diferentes navegadores implementan esto de manera 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 último IE7 más seguro redirigirá la solicitud POST del dominio A al dominio B sin ningún aviso o diálogo de confirmación. Safari también actúa de una manera interesante, mientras que no abre un cuadro de diálogo de confirmación y realiza la redirección, desecha los datos de la POST, cambiando efectivamente la redirección 307 a la 302 más común.
Por lo que sé, la única forma de implementar algo como esto sería usar Javascript. Hay dos opciones que se me ocurren de la cabeza:
- 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 envío que primero ejecuta una solicitud AJAX a su servidor con los datos y luego permite que el formulario se envíe al servidor de terceros. - Crea el formulario para publicar en tu servidor. Cuando se envíe 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 "Redireccionando ...". Luego, agregue un evento 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 visible el botón Enviar para el formulario oculto, y darles instrucciones para que lo presionen si demora más de 5 segundos. En segundo lugar, puede decidir qué datos se transmiten al servidor de terceros; Si solo usa 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, asumiendo que funcionó para todos sus usuarios.
¡Espero que esto ayude!