Publicité
+ Répondre à la discussion
Affichage des résultats 1 à 9 sur 9
  1. #1
    Invité
    Invité(e)

    Par défaut Extension de la classe WebClient pour exposer le Timeout



    La classe ExtendedWebClient dérivant de la classe WebClient vous permet de définir un timeout pour tout instance de la classe WebClient (Cette classe ne le permet pas bien qu'elle utilise la classe HttpWebRequest pour télécharger et téléverser des données).



    Code C# :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
     
    /// <summary>
    /// Classe dérivée de la classe WebClient
    /// </summary>
    public class ExtendedWebClient : WebClient
    {
        #region Fields
     
        private WebRequest request;
     
        #endregion // Fields
     
        #region Properties
     
        /// <summary>
        /// Obtient la durée du timeout
        /// </summary>
        public int Timeout { get; private set; }
     
        /// <summary>
        /// Obtient le container de cookies
        /// </summary>
        public CookieContainer CookieContainer { get; private set; }
     
        #endregion // Properties
     
        #region  Consctuctors
     
        /// <summary>
        /// Constructeur de la classe ExtendedWebClient
        /// </summary>
        /// <param name="timeout">Durée en millisecondes </param>
        public ExtendedWebClient(int timeout)
        {
            this.Timeout = timeout;
            this.CookieContainer = new CookieContainer();
        }
     
        #endregion // Constructors
     
        #region Overriden methods
     
        protected override WebRequest GetWebRequest(Uri address)
        {
            this.request = base.GetWebRequest(address);
     
            // S'il s'agit d'une instance de type HttpWebRequest alors on instancie le container de cookie
            if (this.request is HttpWebRequest)
            {
                (this.request as HttpWebRequest).CookieContainer = this.CookieContainer;
            }
     
            // Si this.Timeout <= 0 alors la valeur par défaut qui sera utilisée.
            this.request.Timeout = this.Timeout <= 0 ? this.request.Timeout : this.Timeout;
            return this.request;
        }
     
        #endregion // Overriden methods
    }
    Dernière modification par Invité ; 09/05/2012 à 13h54.

  2. #2
    Rédacteur/Modérateur



    Homme Profil pro Thomas Levesque
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 293
    Détails du profil
    Informations personnelles :
    Nom : Homme Thomas Levesque
    Âge : 33
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2004
    Messages : 19 293
    Points : 39 083
    Points
    39 083

    Par défaut

    Oui, et pendant qu'on y est on peut aussi ajouter la gestion des cookies et autres réglages avancés

  3. #3
    Invité
    Invité(e)

    Par défaut

    Citation Envoyé par tomlev Voir le message
    Oui, et pendant qu'on y est on peut aussi ajouter la gestion des cookies et autres réglages avancés
    Yep! Pas faux. Sauf qu'en appliquant le principe YAGNI à mon projet actuel j'ai juste ajouté ce dont j'avais besoin .
    Sinon j'ajouterai volontiers ces réglages avancés et mettrai à jour le post une fois fait.

  4. #4
    Invité
    Invité(e)

    Par défaut

    J'ai mis à jour le post initial et voici les éléments suivants :
    • Ajout d'une propriété CookieContainer pour de la gestion des cookies (uniquement pour les requêtes HTTP/S)
    • Ajout d'une nouvelle méthode Abort pour abandonner une requête en cours d'exécution.
      Attention avec cette méthode, elle ne met pas à jour la propriété Cancelled qu'on récupère dans les gestionnaires d'évènement des différentes méthodes asynchrones qu'on sera amenées à utiliser. Il faudra se baser sur la propriété Status de l'erreur renvoyée en convertissant celle-ci en type WebException. Bref un petit exemple :
      Code C# :
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
       
      class Program
      {
          static void Main(string[] args)
          {
              ExtendedWebClient client = new ExtendedWebClient(5 * 60 * 1000);
              client.DownloadDataCompleted += clientDownloadDataCompleted;
              client.DownloadDataAsync(new Uri("http://www.developpez.com"));
              client.Abort();
              Console.ReadKey();
          }
       
          private static void clientDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
          {
       
              WebException we = e.Error as WebException;
              if (we != null)
              {
                  // On regarde la propriété Status de l'objet WebException parce que e.Cancelled vaut toujours false 
                  // lorsqu'on abandonne notre précédente requête.
                  if (we.Status == WebExceptionStatus.RequestCanceled)
                  {
                      Console.WriteLine("Abandon : {0}", we.Message);
                  }
                  else
                  {
                      Console.WriteLine("Autre chose : {0}", we.Message);
                  }
              }
              else if (e.Error != null)
              {
                  Console.WriteLine("Autre chose : {0}", e.Error.Message);
              }
              else
              {
                  Console.WriteLine("Appramment tout s'est bien passé");
              }
          }
      }


    Si vous avez d'autres choses à ajouter à cette classe alors n'hésitez pas.

  5. #5
    Rédacteur/Modérateur



    Homme Profil pro Thomas Levesque
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 293
    Détails du profil
    Informations personnelles :
    Nom : Homme Thomas Levesque
    Âge : 33
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2004
    Messages : 19 293
    Points : 39 083
    Points
    39 083

    Par défaut

    Citation Envoyé par h2s84 Voir le message
    [*] Ajout d'une nouvelle méthode Abort pour abandonner une requête en cours d'exécution.
    Euh, c'est cool, mais ça existe déjà : CancelAsync
    Et ça met bien à jour la propriété Cancelled

    Pour le CookieContainer, à mon avis tu le gères pas comme il faudrait :
    - il faut qu'il soit initialisé avant le GetWebRequest, sinon l'utilisateur peut pas ajouter des Cookies à envoyer avec la requête
    - il ne faut pas le réinitialiser à chaque fois, mais le réutiliser pour les requêtes suivantes. Comme ça les cookies sont automatiquement retransmis au serveur (cookies d'authentification par exemple)

  6. #6
    Invité
    Invité(e)

    Par défaut

    Citation Envoyé par tomlev Voir le message
    Euh, c'est cool, mais ça existe déjà : CancelAsync
    Et ça met bien à jour la propriété Cancelled
    hum... Coment j'ai pu manqué ça. Ok c'est retiré

    Citation Envoyé par tomlev Voir le message
    Pour le CookieContainer, à mon avis tu le gères pas comme il faudrait :
    - il faut qu'il soit initialisé avant le GetWebRequest, sinon l'utilisateur peut pas ajouter des Cookies à envoyer avec la requête
    Je n'ai pas trop compris mais un autre problème est que je me demande où est-ce que je vais pouvoir la mettre l'inistialisation surtout que j'ai besoin de savoir s'il s'agit d'une HttpWebRequest ? Je cherche...

    Citation Envoyé par tomlev Voir le message
    - il ne faut pas le réinitialiser à chaque fois, mais le réutiliser pour les requêtes suivantes. Comme ça les cookies sont automatiquement retransmis au serveur (cookies d'authentification par exemple)
    Parfaitement raison avec l'exemple de l’authentification. Ok je l'initialise dans le constructeur même si on sait que les cookies sont utiles uniquemeent pour HttpWebRequest.

  7. #7
    Rédacteur/Modérateur



    Homme Profil pro Thomas Levesque
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 293
    Détails du profil
    Informations personnelles :
    Nom : Homme Thomas Levesque
    Âge : 33
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2004
    Messages : 19 293
    Points : 39 083
    Points
    39 083

    Par défaut

    Citation Envoyé par h2s84 Voir le message
    Je n'ai pas trop compris
    Si je fais ça avec ton code d'origine, ça plante :
    Code :
    1
    2
    var wc = new ExtendedWebClient();
    wc.CookieContainer.Add(...); // NullReferenceException
    Et même si CookieContainer est initialisé dans le constructeur, si tu le réinitialises dans le GetWebRequest les cookies ajoutés avant sont perdus

    Citation Envoyé par h2s84 Voir le message
    mais un autre problème est que je me demande où est-ce que je vais pouvoir la mettre l'inistialisation surtout que j'ai besoin de savoir s'il s'agit d'une HttpWebRequest ? Je cherche...
    Bah tu t'en fous... si c'est pas une HttpWebRequest, tu ignores la propriété CookieContainer.

  8. #8
    Invité
    Invité(e)

    Par défaut

    Citation Envoyé par tomlev Voir le message
    Si je fais ça avec ton code d'origine, ça plante :
    Code :
    1
    2
    var wc = new ExtendedWebClient();
    wc.CookieContainer.Add(...); // NullReferenceException
    Je confirme.

    Citation Envoyé par tomlev Voir le message
    Et même si CookieContainer est initialisé dans le constructeur, si tu le réinitialises dans le GetWebRequest les cookies ajoutés avant sont perdus
    C'est normal... je pense. bah ! Si tu crées une nouvelle instance d'une classe WebClient c'est normal que le CookieContainer soit réinitialiser non ? Je sais tu ne penses pas à mettre cette propriété en statique mais peut-être que tu veux que le container soit passé en paramètre au constructeur ?

    Citation Envoyé par tomlev Voir le message
    Bah tu t'en fous... si c'est pas une HttpWebRequest, tu ignores la propriété CookieContainer.
    Bon finalement je pense que utiliser les Header est plus simple après tout en lisant ceci.

  9. #9
    Rédacteur/Modérateur



    Homme Profil pro Thomas Levesque
    Développeur .NET
    Inscrit en
    février 2004
    Messages
    19 293
    Détails du profil
    Informations personnelles :
    Nom : Homme Thomas Levesque
    Âge : 33
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : février 2004
    Messages : 19 293
    Points : 39 083
    Points
    39 083

    Par défaut

    Citation Envoyé par h2s84 Voir le message
    C'est normal... je pense. bah ! Si tu crées une nouvelle instance d'une classe WebClient c'est normal que le CookieContainer soit réinitialiser non ?
    Si tu crées une nouvelle instance, oui, mais quand tu réinitialisais le CookieContainer dans le GetWebRequest, ça faisait que ce code là ne marchait pas :

    Code :
    1
    2
    3
    var wc = new ExtendedWebClient();
    wc.CookieContainer.Add(...);
    wc.DownloadString(...); // le cookie ajouté au dessus est perdu...
    Avec le code actuel c'est OK

    Citation Envoyé par h2s84 Voir le message
    Je sais tu ne penses pas à mettre cette propriété en statique mais peut-être que tu veux que le container soit passé en paramètre au constructeur ?
    Non, surtout pas en statique ! ça ferait que toutes les instances de la classe partageraient le même CookieContainer, ce qui est extrêmement gênant...
    Le passer en paramètre, c'est possible, mais pas indispensable. Tu peux toujours faire 2 constructeurs...

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •