Wie setze ich ein Cookie in HttpRequestMessage von HttpClient?

246

Ich versuche, die Web-APIs zu verwenden HttpClient, um einen Beitrag an einem Endpunkt zu verfassen, für den eine Anmeldung in Form eines HTTP-Cookies erforderlich ist, das ein Konto identifiziert (dies ist nur etwas, #ifdefdas in der Release-Version enthalten ist).

Wie füge ich dem einen Cookie hinzu HttpRequestMessage?

George Mauer
quelle

Antworten:

373

So können Sie einen benutzerdefinierten Cookie-Wert für die Anforderung festlegen:

var baseAddress = new Uri("http://example.com");
var cookieContainer = new CookieContainer();
using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("foo", "bar"),
        new KeyValuePair<string, string>("baz", "bazinga"),
    });
    cookieContainer.Add(baseAddress, new Cookie("CookieName", "cookie_value"));
    var result = await client.PostAsync("/test", content);
    result.EnsureSuccessStatusCode();
}
Darin Dimitrov
quelle
2
Der Handler kann aus der using-Anweisung entfernt werden. Er wird entsorgt, wenn der http-Client entsorgt wird.
Kimi
17
Kimi ist korrekt, aber Sie sollten Ihren HttpClient auch nicht in eine Verwendung einwickeln. aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong
Robert McLaws
9
VORSICHT: Wenn Sie nur eine Instanz von HttpClient verwenden, um mehrere Anforderungen auszuführen, werden Cookies, die CookieContainer verwenden, zwischengespeichert. Ist gefährlich für einen Benutzer, erhalten Sie das Cookie von einem anderen Benutzer.
Acaz Souza
31
"HttpClient soll einmal instanziiert und während der gesamten Lebensdauer einer Anwendung wiederverwendet werden. Insbesondere in Serveranwendungen wird durch das Erstellen einer neuen HttpClient-Instanz für jede Anforderung die Anzahl der unter hoher Last verfügbaren Sockets erschöpft ..." Von hier aus: asp .net / web-api /
übersicht
4
@SergeyT Was macht man also, wenn man separate Sitzungen mit derselben Sitzung aufrufen muss? :)
AgentFire
336

Die akzeptierte Antwort ist in den meisten Fällen der richtige Weg, dies zu tun. Es gibt jedoch Situationen, in denen Sie den Cookie-Header manuell festlegen möchten. Wenn Sie einen "Cookie" -Header festlegen, wird dieser normalerweise ignoriert. Dies liegt jedoch daran, dass HttpClientHandlerstandardmäßig die CookieContainerEigenschaft für Cookies verwendet wird. Wenn Sie dies deaktivieren, können Sie durch Setzen UseCookiesauf falseCookie-Header manuell festlegen, die in der Anforderung angezeigt werden, z

var baseAddress = new Uri("http://example.com");
using (var handler = new HttpClientHandler { UseCookies = false })
using (var client = new HttpClient(handler) { BaseAddress = baseAddress })
{
    var message = new HttpRequestMessage(HttpMethod.Get, "/test");
    message.Headers.Add("Cookie", "cookie1=value1; cookie2=value2");
    var result = await client.SendAsync(message);
    result.EnsureSuccessStatusCode();
}
Greg Beech
quelle
44
Ich habe mehrere Tage lang einen Fehler verfolgt, bei dem mit SendAsync gesendete Anforderungen den Cookie-Header nicht gesendet haben. Dies half mir zu erkennen, dass, wenn Sie UseCookies = false im Handler nicht festlegen, nicht nur der CookieContainer verwendet wird, sondern auch alle in den Anforderungsheadern gespeicherten Cookies stillschweigend ignoriert werden! Ich danke dir sehr!
Fernando Neira
14
Diese Antwort ist äußerst hilfreich für alle, die versuchen, HttpClient als Proxy zu verwenden!
Cchamberlain
3
Versuchen Sie es jetzt ... wenn es funktioniert ... verdienen Sie eine gute alte kanadische Umarmung.
Maxime Rouiller
11
VORSICHT: Wenn Sie nur eine Instanz von HttpClient verwenden, um mehrere Anforderungen auszuführen, werden Cookies, die CookieContainer verwenden, zwischengespeichert. Ist gefährlich für einen Benutzer, erhalten Sie das Cookie von einem anderen Benutzer.
Acaz Souza
9
Diese dumme Sache sollte eine Ausnahme auslösen, wenn jemand versucht, einen "Cookie" -Header hinzuzufügen, anstatt ihn stillschweigend zu verlieren. Hat mich eine Stunde meines Lebens gekostet. Danke für die Lösung.
stmax
5

Nachdem ich Stunden mit diesem Thema verbracht hatte, half mir keine der obigen Antworten, so dass ich ein wirklich nützliches Werkzeug fand.

Erstens habe ich Teleriks Fiddler 4 verwendet, um meine Webanfragen im Detail zu untersuchen

Zweitens bin ich auf dieses nützliche Plugin für Fiddler gestoßen:

https://github.com/sunilpottumuttu/FiddlerGenerateHttpClientCode

Es wird nur der C # -Code für Sie generiert. Ein Beispiel war:

        var uriBuilder = new UriBuilder("test.php", "test");
        var httpClient = new HttpClient();


        var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uriBuilder.ToString());



        httpRequestMessage.Headers.Add("Host", "test.com");
        httpRequestMessage.Headers.Add("Connection", "keep-alive");
     //   httpRequestMessage.Headers.Add("Content-Length", "138");
        httpRequestMessage.Headers.Add("Pragma", "no-cache");
        httpRequestMessage.Headers.Add("Cache-Control", "no-cache");
        httpRequestMessage.Headers.Add("Origin", "test.com");
        httpRequestMessage.Headers.Add("Upgrade-Insecure-Requests", "1");
    //    httpRequestMessage.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        httpRequestMessage.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36");
        httpRequestMessage.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
        httpRequestMessage.Headers.Add("Referer", "http://www.translationdirectory.com/");
        httpRequestMessage.Headers.Add("Accept-Encoding", "gzip, deflate");
        httpRequestMessage.Headers.Add("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8");
        httpRequestMessage.Headers.Add("Cookie", "__utmc=266643403; __utmz=266643403.1537352460.3.3.utmccn=(referral)|utmcsr=google.co.uk|utmcct=/|utmcmd=referral; __utma=266643403.817561753.1532012719.1537357162.1537361568.5; __utmb=266643403; __atuvc=0%7C34%2C0%7C35%2C0%7C36%2C0%7C37%2C48%7C38; __atuvs=5ba2469fbb02458f002");


        var httpResponseMessage = httpClient.SendAsync(httpRequestMessage).Result;

        var httpContent = httpResponseMessage.Content;
        string result = httpResponseMessage.Content.ReadAsStringAsync().Result;

Beachten Sie, dass ich zwei Zeilen auskommentieren musste, da dieses Plugin noch nicht ganz perfekt ist, aber es hat trotzdem funktioniert.

HAFTUNGSAUSSCHLUSS: Ich bin weder mit Telerik noch mit dem Autor des Plugins verbunden oder unterstützt.

Amir No-Family
quelle
2
Dies ist im Wesentlichen die gleiche Antwort wie diese . Der einzige Teil, der mit Cookies zu tun hat, ist das letzte Hinzufügen eines Headers. Beachten Sie alle Vorbehalte in dieser Antwort
George Mauer
4

Für mich funktioniert die einfache Lösung, um Cookies im HttpRequestMessage- Objekt zu setzen.

protected async Task<HttpResponseMessage> SendRequest(HttpRequestMessage requestMessage, CancellationToken cancellationToken = default(CancellationToken))
{
    requestMessage.Headers.Add("Cookie", $"<Cookie Name 1>=<Cookie Value 1>;<Cookie Name 2>=<Cookie Value 2>");

    return await _httpClient.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
}
Waqar UlHaq
quelle
Beachten Sie, dass die akzeptierte Antwort eine Tonne mehr bewirkt und viel mehr Randbedingungen als diese verarbeitet. Es kann verwendet werden, um Dinge wie nur http oder Cookies mit Gültigkeitsbereich, mehrwertige Cookies usw. usw. zu tun. Die zweithöchste Antwort schlägt die gleiche Methode vor, jedoch mit viel mehr Kontext und Erklärung
George Mauer
@ GeorgeMauer kann sein, dass Sie Recht haben. Beide erstellen httpClient aus "HttpClient (Handler)". In meinem Fall erstelle ich _httpClient aus httpClientPool.GetOrCreateHttpClient ()
Waqar UlHaq
1
Aber Sie zeigen das in Ihrer Antwort nicht wirklich und erklären auch nicht den Unterschied oder die Vorteile (es ist auch nicht wirklich die Frage, aber ich mache mir darüber keine Sorgen). Ich versuche nicht unhöflich zu sein, es ist nur wichtig klar zu sein, wem diese Antwort hilfreich wäre, und die anderen würden nicht besser helfen.
George Mauer