Al usar WebClient en C #, ¿hay alguna manera de obtener la URL de un sitio después de ser redirigido?

Al usar la clase WebClient puedo obtener el título de un sitio web con la suficiente facilidad:

WebClient x = new WebClient(); string source = x.DownloadString(s); string title = Regex.Match(source, @"\]*\>\s*(?<Title>[\s\S]*?)\", RegexOptions.IgnoreCase).Groups["Title"].Value; 

Quiero almacenar la URL y el título de la página. Sin embargo, al seguir un enlace como:

http://tinyurl.com/dbysxp

Obviamente voy a querer obtener la URL a la que me redirigen.

PREGUNTAS

¿Hay alguna manera de hacer esto usando la clase WebClient ?

¿Cómo lo haría usando HttpResponse y HttpRequest ?

Si entiendo la pregunta, es mucho más fácil de lo que la gente dice: si quiere que WebClient haga todos los detalles de la solicitud (incluida la redirección), pero luego obtenga el URI de respuesta real al final, puede crear una subclase WebClient. Me gusta esto:

 class MyWebClient : WebClient { Uri _responseUri; public Uri ResponseUri { get { return _responseUri; } } protected override WebResponse GetWebResponse(WebRequest request) { WebResponse response = base.GetWebResponse(request); _responseUri = response.ResponseUri; return response; } } 

Simplemente use MyWebClient en todos los sitios en los que haya utilizado WebClient. Una vez que haya realizado la llamada de WebClient que necesitaba, puede usar ResponseUri para obtener el URI redirigido real. Debería agregar una anulación similar para GetWebResponse (solicitud de WebRequest, resultado de IAsyncResult) también, si estuviera utilizando las funciones de asincronización.

Sé que esta es una pregunta ya respondida, pero esto me funciona bastante bien:

  HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://tinyurl.com/dbysxp"); request.AllowAutoRedirect = false; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); string redirUrl = response.Headers["Location"]; response.Close(); //Show the redirected url MessageBox.Show("You're being redirected to: "+redirUrl); 

Aclamaciones.! 😉

Con una HttpWebRequest , establecería la propiedad AllowAutoRedirect en false . Cuando esto sucede, cualquier respuesta con un código de estado entre 300-399 no se redirigirá automáticamente.

A continuación, puede obtener la nueva URL de los encabezados de respuesta y luego crear una nueva instancia de HttpWebRequest en la nueva url.

Con la clase WebClient , dudo que pueda cambiarla de inmediato para que no permita redirecciones. Lo que podría hacer es derivar una clase de la clase WebClient y luego anular los GetWebRequest y GetWebResponse para alterar las instancias WebRequest / WebResponse que devuelve la implementación base; si es una HttpWebRequest , establezca la propiedad AllowAutoRedirect en false . En la respuesta, si el código de estado está en el rango de 300-399, emita una nueva solicitud.

Sin embargo, no sé si puede emitir una nueva solicitud desde los métodos GetWebRequest / GetWebResponse , por lo que sería mejor tener un bucle que se ejecute con HttpWebRequest / HttpWebResponse hasta que se HttpWebResponse todos los redireccionamientos.

Obtuve el Uri para la página redirigida y el contenido de la página.

 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(strUrl); request.AllowAutoRedirect = true; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream dataStream = response.GetResponseStream(); strLastRedirect = response.ResponseUri.ToString(); StreamReader reader = new StreamReader(dataStream); string strResponse = reader.ReadToEnd(); response.Close(); 

En caso de que solo esté interesado en el URI de redirección, puede usar este código:

 public static string GetRedirectUrl(string url) { HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create(url); request.AllowAutoRedirect = false; using (HttpWebResponse response = HttpWebResponse)request.GetResponse()) { return response.Headers["Location"]; } } 

El método volverá

  • nulo – en caso de no redirigir
  • una URL relativa – en caso de una redirección

Tenga en cuenta : la instrucción using (o una response.close() ) es esencial. Ver MSDN Library para más detalles. De lo contrario, puede que se quede sin conexiones u obtenga un tiempo de espera excedido al ejecutar este código varias veces.

HttpWebRequest.AllowAutoRedirect se puede establecer en falso. Entonces tendrías que manualmente códigos de estado http en el rango 300.

 // Create a new HttpWebRequest Object to the mentioned URL. HttpWebRequest myHttpWebRequest=(HttpWebRequest)WebRequest.Create("http://www.contoso.com"); myHttpWebRequest.MaximumAutomaticRedirections=1; myHttpWebRequest.AllowAutoRedirect=true; HttpWebResponse myHttpWebResponse=(HttpWebResponse)myHttpWebRequest.GetResponse(); 

La clase WebClient tiene una opción para seguir redirecciones. Establezca esa opción y debería estar bien.

Bueno, esto es realmente hackish, pero la clave es usar HttpWebRequest y luego establecer la propiedad AllowAutoRedirect en verdadero.

Aquí hay un ejemplo MUY pirateado

  HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://tinyurl.com/dbysxp"); req.Method = "GET"; req.AllowAutoRedirect = true; WebResponse response = req.GetResponse(); response.GetResponseStream(); Stream responseStream = response.GetResponseStream(); // Content-Length header is not trustable, but makes a good hint. // Responses longer than int size will throw an exception here! int length = (int)response.ContentLength; const int bufSizeMax = 65536; // max read buffer size conserves memory const int bufSizeMin = 8192; // min size prevents numerous small reads // Use Content-Length if between bufSizeMax and bufSizeMin int bufSize = bufSizeMin; if (length > bufSize) bufSize = length > bufSizeMax ? bufSizeMax : length; StringBuilder sb; // Allocate buffer and StringBuilder for reading response byte[] buf = new byte[bufSize]; sb = new StringBuilder(bufSize); // Read response stream until end while ((length = responseStream.Read(buf, 0, buf.Length)) != 0) sb.Append(Encoding.UTF8.GetString(buf, 0, length)); string source = sb.ToString();string title = Regex.Match(source, @"\]*\>\s*(?[\s\S]*?)\</title\>",RegexOptions.IgnoreCase).Groups["Title"].Value; 

enter code here