2009-03-27 5 views
37

Utilisation de la classe WebClient je peux obtenir le titre d'un site web assez facilement:Utiliser WebClient en C# est-il possible d'obtenir l'URL d'un site après avoir été redirigé?

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

Je veux enregistrer l'URL et le titre de la page. Cependant lorsque l'on suit un lien tel que:

http://tinyurl.com/dbysxp

Je vais vouloir clairement obtenir l'URL que je suis redirigé.

QUESTIONS

Est-il possible de le faire en utilisant la classe WebClient? Comment le faire en utilisant HttpResponse et HttpRequest?

Répondre

60

Si je comprends bien la question, il est beaucoup plus facile que les gens disent - si vous voulez laisser WebClient faire tous les écrous et boulons du demande (y compris la redirection), mais obtenir l'URI de réponse réelle à la fin, vous pouvez sous-classe WebClient comme ceci:

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; 
    } 
} 

Utilisez simplement MyWebClient partout où vous auriez utilisé WebClient. Une fois que vous avez effectué l'appel WebClient nécessaire, vous pouvez simplement utiliser ResponseUri pour obtenir l'URI réellement redirigé. Vous devez également ajouter un remplacement similaire pour GetWebResponse (requête WebRequest, résultat IAsyncResult) si vous utilisiez le composant asynchrone.

+1

Cela ne fonctionnera pas si vous téléchargez async (par exemple, en utilisant 'DownloadStringAsync'), mais cela fonctionne très bien pour les appels synchrones. – nateirvin

+0

Pourquoi n'avez-vous pas simplement suggéré de faire ce que vous avez fait dans la méthode prioritaire au lieu d'étendre la classe entière lol? – GabrielBB

+7

@GabrielBB - GetWebResponse est protégé, vous ne pouvez donc y accéder que dans une sous-classe de WebClient. –

6

Avec un HttpWebRequest, vous devez définir AllowAutoRedirect property sur false. Lorsque cela se produit, toute réponse avec un code d'état compris entre 300 et 399 ne sera pas automatiquement redirigée.

Vous pouvez ensuite obtenir le nouvel URL à partir des en-têtes de réponse, puis créer une nouvelle instance HttpWebRequest dans la nouvelle URL.

Avec le WebClient class, je doute que vous puissiez le modifier de façon à ce qu'il n'autorise pas les redirections. Ce que vous pouvez faire est dériver une classe de la classe WebClient, puis remplacer les GetWebRequest et les méthodes GetWebResponse pour modifier les instances WebRequest/WebResponse renvoyées par l'implémentation de base; S'il s'agit d'un HttpWebRequest, définissez la propriété AllowAutoRedirect sur false. Sur la réponse, si le code d'état est compris entre 300 et 399, émettez une nouvelle requête.

Cependant, je ne sais pas que vous pouvez émettre une nouvelle demande dans les méthodes GetWebRequest/GetWebResponse, il pourrait être préférable d'avoir juste une boucle qui exécute avec HttpWebRequest/HttpWebResponse jusqu'à ce que toutes les redirections sont suivies.

+1

Avez-vous une chance de donner un exemple de ce que vous feriez? –

+1

un échantillon à ce sujet? – Kiquenet

-1

La classe WebClient dispose d'une option permettant de suivre les redirections. Réglez cette option et vous devriez aller bien.

0

HttpWebRequest.AllowAutoRedirect peut être défini sur false. Ensuite, vous devrez manuellement les codes d'état http dans la gamme 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(); 
-1

Ok c'est vraiment hackish, mais la clé est d'utiliser le HttpWebRequest puis définissez la propriété AllowAutoRedirect true.

est ici un très piraté ensemble par exemple

 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, 
     @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>",RegexOptions.IgnoreCase).Groups["Title"].Value; 

enter code here

16

Je sais ce qui est déjà une réponse à votre question, mais cela fonctionne assez pour moi:

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); 

Vive.! ;)

+0

Exellent! Cela a fonctionné – GabrielBB

+2

Il est essentiel de finalement appeler 'response.close()' (ou d'utiliser une instruction 'using'). Voir https://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.getresponse(v=vs.110).aspx pour plus de détails. Sinon, vous risquez de manquer de connexions ou d'obtenir un délai d'expiration lors de l'exécution de ce code plusieurs fois. – JimiLoe

+0

Merci pour l'ajout, Jimi! – WhySoSerious

3

J'ai obtenu l'Uri pour la page redirigée et le contenu de la page.

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(); 
2

Si vous ne souhaitez que la redirection URI vous pouvez utiliser ce code:

La méthode retourne

  • null - en cas de non redirect
  • une url relative - dans le cas d'une redirection

Veuillez noter: L'instruction using (ou une dernière response.close()) est essentielle. Voir MSDN Library pour plus de détails. Sinon, vous risquez de manquer de connexions ou d'obtenir un délai d'expiration lors de l'exécution de ce code plusieurs fois.

Questions connexes