Accueil > Articles > Configurer un proxy dans une application C#

Configurer un proxy dans une application C#

Le .NET Framework fournit de nombreuses classes pour gérer les transferts de données via Internet, qui ne sont pas seulement utiles pour les applications web. L’espace de nom System.Net peut aussi servir à des applications Windows, pour mettre au point un système de mises à jour automatiques, gérer un ftp, télécharger un fichier, etc. Pour tout ce qui concerne les communications réseau en fait. Cependant une application Windows qui souhaite envoyer une simple requête Http (à l’aide d’un objet WebRequest) peut très bien fonctionner sur un réseau domestique, mais être systématiquement bloquée sur un réseau d’entreprise. En général, cela se traduit par une « WebException » avec pour détails : « The remote server returned an error: (407) Proxy Authentication Required. ». Comme le message l’indique, il s’agit en fait du proxy qui pose problème ici et bloque toute requête qui ne s’identifie pas correctement. Il est donc important de prévoir ce cas si l’on développe un client lourd (application Console ou Windows) destiné à être déployé publiquement et utilisant les objets de System.Net.

On va donc partir d’un code relativement simple, puisqu’il s’agit d’effectuer une petite requête Web (avec un objet WebRequest) et d’en récupérer le résultat :

WebRequest request = WebRequest.Create("http://www.google.fr");
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadLine();

Note : N’oubliez pas d’ajouter l’assembly Microsoft.System.Net aux références du projet.

Cet exemple de code provoque l’erreur 407 : Proxy Authentication Required si le réseau est muni d’un proxy. On va donc définir sa configuration et la méthode d’authentification pour que notre requête puisse passer.

 

1ère méthode : Définir manuellement la configuration du proxy

 

La première étape consiste à récupérer la configuration du proxy. Pas besoin de demander à l’administrateur du réseau pour ça, en général Internet Explorer doit déjà être correctement configuré. Il suffit donc d’aller regarder les paramètres de configuration :

Options IE

Options IE

On a besoin de deux données : une adresse web et un numéro de port. Dans cet exemple, il s’agit de « proxyhttp » et du port 8080 :

Options réseau

Options réseau

Je ne présente ici que le moyen de récupérer ces informations dans Internet Explorer. Il est très rare que d’autres explorateurs Internet (comme Firefox) soient autorisés sur les réseaux d’entreprises.

On modifie ensuite le code précédent pour créer un objet WebProxy et le fournir à notre WebRequest :

Uri testUri = new Uri("http://www.google.fr");
WebRequest request = WebRequest.Create(testUri);

// Proxy
WebProxy myProxy = new WebProxy("http://proxyhttp:8080/", true);
myProxy.Credentials = CredentialCache.DefaultCredentials;
myProxy.UseDefaultCredentials = true;
request.Proxy = myProxy;

// Result
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadLine();
Console.WriteLine(result);

Normalement, tout devrait maintenant fonctionner. Attention toutefois à ne pas oublier de définir le mode d’authentification du proxy (les « credentials ») sous peine d’obtenir à nouveau le même message d’erreur !

 

2ème méthode : Récupérer automatiquement la configuration du proxy

 

Récupérer manuellement la configuration du proxy est donc relativement simple à effectuer. Cependant si l’on souhaite distribuer l’application, le fait de demander à l’utilisateur de définir lui-même la configuration de son proxy peut être gênant. Une solution pour récupérer automatiquement ces paramètres serait plus intéressante dans ce cas.

Heureusement il est possible de laisser le .NET Framework s’occuper de tout en utilisant une autre méthode pour définir le proxy de notre objet WebRequest :

request.Proxy = WebProxy.GetDefaultProxy();

La récupération du proxy par défaut ne suffit pas, il faut aussi ajouter les informations d’identification (les « credentials ») :

request.Proxy = WebProxy.GetDefaultProxy();
request.Proxy.Credentials = CredentialCache.DefaultCredentials;

Et voilà, ça fonctionne sans avoir à récupérer l’adresse et le port du proxy !
Cependant, depuis la version 2.0 du .NET Framework, la méthode WebProxy.GetDefaultProxy() est signalée comme étant obsolète par l’alerte suivante :

‘System.Net.WebProxy.GetDefaultProxy()’ is obsolete: ‘This method has been deprecated. Please use the proxy selected for you by default. http://go.microsoft.com/fwlink/?linkid=14202

On va donc faire les choses proprement et écrire le code avec les nouvelles méthodes. Microsoft nous facilite les choses en plus en indiquant le lien à visiter pour avoir plus d’informations. Sauf que le lien n’est plus valable et amène à la page d’accueil de MSDN… Et la page concernant la méthode GetDefaultProxy ne donne aucune indication sur le nouveau code à utiliser. Voilà un exemple de mauvais suivi de la documentation à ne surtout pas suivre ! Heureusement qu’il y a les commentaires des utilisateurs un peu plus bas, qui indiquent la nouvelle méthode à utiliser, il s’agit de la propriété WebRequest.DefaultWebProxy :

request.Proxy = WebRequest.DefaultWebProxy;

En y réfléchissant un peu, notre variable request est déjà un objet de type WebRequest. Le proxy par défaut devrait donc être directement disponible dans chaque instance de WebRequest. D’ailleurs en enlevant cette ligne, on constate finalement que ça fonctionne aussi sans problème. Par contre ce n’est pas le cas de l’identification et des « credentials », mais comme cela se défini au niveau du proxy, on va profiter du fait que la propriété DefaultWebProxy soit disponible en écriture pour mettre l’identification par défaut à toutes les instances de WebRequest :

WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;

Voilà le code final :

// Proxy
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;

//Result
Uri testUri = new Uri("http://www.google.fr");
WebRequest request = WebRequest.Create(testUri);

// Result
WebResponse response = request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string result = reader.ReadLine();
Console.WriteLine(result);

 

3ème méthode : Définir le proxy dans le fichier .config

 

Pour ceux qui ne souhaitent pas définir le paramétrage du proxy dans le code, il est possible de le mettre dans le fichier .config de l’application. Pour définir l’adresse et le port du proxy il faut utiliser les données XML suivantes :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <system.net>
      <defaultProxy useDefaultCredentials="true">
         <proxy proxyaddress="http://proxyhttp:8080/"
            bypassonlocal="True"
         />
      </defaultProxy>
   </system.net>
</configuration>

Et pour la détection du proxy par défaut :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <system.net>
      <defaultProxy useDefaultCredentials="true">
         <proxy usesystemdefault="True" />
      </defaultProxy>
   </system.net>
</configuration>

Mais dans la plupart des cas, il suffit juste d’écrire :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
   <system.net>
      <defaultProxy useDefaultCredentials="true" />
   </system.net>
</configuration>

On remarquera que la propriété useDefaultCredentials contient des majuscules et n’accepte que les valeurs true/false écrites en minuscules, alors que la plupart des autres attributs s’écrivent entièrement en minuscules avec des valeurs True/False écrites avec la première lettre en majuscule… Et si on ne respecte pas ça, le validateur XML réagit bruyamment. Heureusement que l’Intellisense nous permet d’éviter les prises de tête à ce sujet.

 

Conclusion

 

Voilà, un article assez long pour un résultat finalement très simple, mais qui m’a demandé pas mal de temps pour y parvenir et surtout pour épurer tout ce que j’ai pu trouver à ce sujet sur Internet. Personnellement, je ne comprend pas trop pourquoi on est obligé de dire explicitement que l’on souhaite utiliser l’identification par défaut. Ce paramétrage devrait être utilisé automatiquement lorsque rien n’est spécifié. L’absence de documentation claire dans MSDN sur la simplification du proxy par défaut pour les WebRequest est aussi bien regrettable.

Pour ceux qui souhaitent aller un peu plus loin sur ce sujet, voici le lien MSDN : Accessing the Internet Throught a Proxy (la traduction française n’est pas disponible apparemment). Attention toutefois, leurs exemples de code sont souvent remplis d’erreurs, en particulier pour les tags XML du fichier de configuration.

 

Categories: Articles Tags: , , , ,
  1. Pas encore de commentaire
  1. Pas encore de trackbacks