Berjuang mencoba mengeluarkan cookie dari respons dengan HttpClient di .net 4.5

107

Saya mendapat kode berikut yang berfungsi dengan sukses. Saya tidak tahu bagaimana mengeluarkan cookie dari respon. Tujuan saya adalah saya ingin dapat mengatur cookie dalam permintaan dan mengeluarkan cookie dari respons. Pikiran?

private async Task<string> Login(string username, string password)
{
    try
    {
        string url = "http://app.agelessemail.com/account/login/";
        Uri address = new Uri(url);
        var postData = new List<KeyValuePair<string, string>>
        {
            new KeyValuePair<string, string>("username", username),
            new KeyValuePair<string, string>("password ", password)
        };

        HttpContent content = new FormUrlEncodedContent(postData);
        var cookieJar = new CookieContainer();
        var handler = new HttpClientHandler
        {
            CookieContainer = cookieJar,
            UseCookies = true,
            UseDefaultCredentials = false
        };

        var client = new HttpClient(handler)
        {
            BaseAddress = address
        };


        HttpResponseMessage response = await client.PostAsync(url,content);
        response.EnsureSuccessStatusCode();
        string body = await response.Content.ReadAsStringAsync();
        return body;
    }
    catch (Exception e)
    {
        return e.ToString();
    }
}

Inilah jawaban lengkapnya:

HttpResponseMessage response = await client.PostAsync(url,content);
response.EnsureSuccessStatusCode();

Uri uri = new Uri(UrlBase);
var responseCookies = cookieJar.GetCookies(uri);
foreach (Cookie cookie in responseCookies)
{
    string cookieName = cookie.Name;
    string cookieValue = cookie.Value;
}
Peter Kellner
sumber
Karena penasaran, dapatkah saya bertanya mengapa Anda ingin membaca cookie di klien? Pemahaman saya adalah bahwa cookie digunakan untuk mengirimkan informasi ke server, bukan untuk mengembalikan informasi.
Darrel Miller
Saya menggunakan cookie yang dikembalikan pada panggilan yang mengembalikan JSON sehingga saya tidak perlu melakukan panggilan otorisasi terpisah untuk setiap panggilan JSON. Artinya, saya memiliki log panggilan / Home / GetData yang mengembalikan JSON tetapi hanya jika diotorisasi. Atas permintaan klien, saya menambahkan cookie sehingga / Home / GetData akan merespons. Jika tidak, akan muncul tulisan "403" tidak sah.
Peter Kellner
Menetapkan header otorisasi sebagai header default hampir sama efektifnya dan sedikit lebih standar. Tidak ada cara bagi server untuk menyetel header autentikasi secara otomatis atas nama klien.
Darrel Miller
1
terima kasih atas tipnya Darrel. Apakah Anda memiliki contoh seperti apa tampilan di asp.net? Saya berjuang dengan ini untuk monotouch saya dan sekarang aplikasi windows store saya. Saya akan senang jika ada cara yang sederhana. Ini menyebalkan, terutama dengan async dan sekarang menunggu di aplikasi windows store.
Peter Kellner

Jawaban:

170

Untuk menambahkan cookie ke permintaan, isi wadah cookie sebelum permintaan dengan CookieContainer.Add(uri, cookie). Setelah permintaan dibuat, wadah cookie akan secara otomatis diisi dengan semua cookie dari respons. Anda kemudian dapat memanggil GetCookies () untuk mengambilnya kembali.

CookieContainer cookies = new CookieContainer();
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookies;

HttpClient client = new HttpClient(handler);
HttpResponseMessage response = client.GetAsync("http://google.com").Result;

Uri uri = new Uri("http://google.com");
IEnumerable<Cookie> responseCookies = cookies.GetCookies(uri).Cast<Cookie>();
foreach (Cookie cookie in responseCookies)
    Console.WriteLine(cookie.Name + ": " + cookie.Value);

Console.ReadLine();
Despertar
sumber
8
Catatan: Setelah menerima cookie awal di panggilan pertama, saat mengakses halaman mana pun dari domain yang sama, cookie akan dikirim secara otomatis, tidak perlu langkah tambahan.
Jahmic
Anda harus menambahkan "menggunakan System.linq;"
Cabuxa.Mapache
^^ System.Linq hanya diperlukan jika Anda ingin menggunakan metode .Cast <>, metode ini tidak diperlukan untuk pengambilan cookie, tetapi ini sudah cukup jelas :)
MikeDub
Apakah mungkin mendapatkan cookie dengan cara yang sama jika httpclientdibuat dari pabrik httpclient? yaitu metode pembangun ditambahkan ke layanan.AddHttpClient
user3279954
di get Async kita sudah membuat referensi ke "google.com", mengapa kita perlu mendeklarasikan URI dengan referensi ke sana lagi?
Malcolm Salvador
7

Ada alternatif lain jika Anda tidak memiliki akses ke HttpClientdan tidak dapat menyuntikkan CookieContainer. Ini berfungsi di .NET Core 2.2:

private string GetCookie(HttpResponseMessage message)
{
    message.Headers.TryGetValues("Set-Cookie", out var setCookie);
    var setCookieString = setCookie.Single();
    var cookieTokens = setCookieString.Split(';');
    var firstCookie = cookieTokens.FirstOrDefault();
    var keyValueTokens = firstCookie.Split('=');
    var valueString = keyValueTokens[1];
    var cookieValue = HttpUtility.UrlDecode(valueString);
    return cookieValue;
}
Rytis I
sumber
1
Cemerlang dan mentah tapi hanya yang saya butuhkan ... Kerja bagus, terima kasih.
Vedran Mandić
5

Anda bisa dengan mudah mendapatkan nilai cookie dengan URL yang diberikan.

private async Task<string> GetCookieValue(string url, string cookieName)
{
    var cookieContainer = new CookieContainer();
    var uri = new Uri(url);
    using (var httpClientHandler = new HttpClientHandler
    {
        CookieContainer = cookieContainer
    })
    {
        using (var httpClient = new HttpClient(httpClientHandler))
        {
            await httpClient.GetAsync(uri);
            var cookie = cookieContainer.GetCookies(uri).Cast<Cookie>().FirstOrDefault(x => x.Name == cookieName);
            return cookie?.Value;
        }
    }
}
Alper Ebicoglu
sumber