J’ai déjà utilisé un CookieContainer avec les sessions HttpWebRequest et HttpWebResponse, mais maintenant je veux l’utiliser avec un WebClient. Pour autant que je sache, il n’y a pas de méthode intégrée comme pour HttpWebRequests ( request.CookieContainer
). Comment puis-je collecter des cookies d’un WebClient dans un CookieContainer?
Je l’ai cherché sur Google et j’ai trouvé l’exemple suivant :
public class CookieAwareWebClient : WebClient { private readonly CookieContainer m_container = new CookieContainer(); protected override WebRequest GetWebRequest(Uri address) { WebRequest request = base.GetWebRequest(address); HttpWebRequest webRequest = request as HttpWebRequest; if (webRequest != null) { webRequest.CookieContainer = m_container; } return request; } }
Est-ce la meilleure façon de le faire?
Oui. À mon humble avis, le remplacement de GetWebRequest () est la meilleure solution pour la fonctionnalité limitée de WebClient. Avant que je sache à propos de cette option, j’ai écrit beaucoup de code très douloureux sur la couche HttpWebRequest car WebClient faisait presque, mais pas tout à fait, ce dont j’avais besoin. La dérivation est beaucoup plus facile.
Une autre option consiste à utiliser la classe WebClient standard, mais à remplir manuellement l’en-tête Cookie avant de faire la demande, puis à retirer l’en-tête Set-Cookies de la réponse. Il existe des méthodes d’assistance sur la classe CookieContainer qui facilitent la création et l’parsing de ces en-têtes: respectivement CookieContainer.SetCookies()
et CookieContainer.GetCookieHeader()
.
Je préfère l’approche précédente car elle est plus facile pour l’appelant et nécessite moins de code répétitif que la deuxième option. En outre, l’approche de dérivation fonctionne de la même manière pour plusieurs scénarios d’extensibilité (par exemple, cookies, proxies, etc.).
WebClient wb = new WebClient(); wb.Headers.Add(HttpRequestHeader.Cookie, "somecookie");
De commentaires
Comment formatez-vous le nom et la valeur du cookie à la place de “somecookie”?
wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename=cookievalue");
Pour plusieurs cookies:
wb.Headers.Add(HttpRequestHeader.Cookie, "cookiename1=cookievalue1;" + "cookiename2=cookievalue2");
Celui-ci est juste une extension de l’article que vous avez trouvé.
public class WebClientEx : WebClient { public WebClientEx(CookieContainer container) { this.container = container; } public CookieContainer CookieContainer { get { return container; } set { container= value; } } private CookieContainer container = new CookieContainer(); protected override WebRequest GetWebRequest(Uri address) { WebRequest r = base.GetWebRequest(address); var request = r as HttpWebRequest; if (request != null) { request.CookieContainer = container; } return r; } protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) { WebResponse response = base.GetWebResponse(request, result); ReadCookies(response); return response; } protected override WebResponse GetWebResponse(WebRequest request) { WebResponse response = base.GetWebResponse(request); ReadCookies(response); return response; } private void ReadCookies(WebResponse r) { var response = r as HttpWebResponse; if (response != null) { CookieCollection cookies = response.Cookies; container.Add(cookies); } } }
HttpWebRequest modifie le CookieContainer qui lui est assigné. Il n’est pas nécessaire de traiter les cookies renvoyés. Atsortingbuez simplement votre conteneur de cookies à chaque requête Web.
public class CookieAwareWebClient : WebClient { public CookieContainer CookieContainer { get; set; } = new CookieContainer(); protected override WebRequest GetWebRequest(Uri uri) { WebRequest request = base.GetWebRequest(uri); if (request is HttpWebRequest) { (request as HttpWebRequest).CookieContainer = CookieContainer; } return request; } }
Je pense qu’il existe un moyen plus propre de ne pas créer un nouveau client Web (et cela fonctionnera également avec les bibliothèques tierces)
internal static class MyWebRequestCreator { private static IWebRequestCreate myCreator; public static IWebRequestCreate MyHttp { get { if (myCreator == null) { myCreator = new MyHttpRequestCreator(); } return myCreator; } } private class MyHttpRequestCreator : IWebRequestCreate { public WebRequest Create(Uri uri) { var req = System.Net.WebRequest.CreateHttp(uri); req.CookieContainer = new CookieContainer(); return req; } } }
Il ne vous rest plus qu’à choisir les domaines que vous souhaitez utiliser:
WebRequest.RegisterPrefix("http://example.com/", MyWebRequestCreator.MyHttp);
Cela signifie que toute demande de don qui va à example.com utilisera désormais votre créateur de réponse personnalisé, y compris le client Web standard. Cette approche signifie que vous n’avez pas à toucher tout votre code. Il vous suffit d’appeler le préfixe du registre une fois et de le terminer. Vous pouvez également vous inscrire au préfixe “http” pour vous inscrire à tout.