遇到傳送 HttpRequest 時需附帶 Cookie 的需求,順手整理 .NET Framework、.NET 6、PowerShell 範例供未來參考。

模擬情境為網站有 AutoRedirect.aspx 及 ShowAndSetCookie.aspx 兩支程式,前者單純導向 ShowAndSetCookie.aspx:

<%@Page Language="C#"%>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
	Response.Redirect("ShowAndSetCookie.aspx");
}
</script>

ShowAndSetCookie.aspx 則讀取名為 ReqId 的 Cookie 並顯示,再設定名為 RespId 的 Cookie:

<%@Page Language="C#"%>
<script runat="server">
void Page_Load(object sender, EventArgs e)
{
	var cookie = Request.Cookies["ReqId"];
	Response.Write("Cookie['ReqId'] = " + (cookie == null ? "N/A" : cookie.Value));
	Response.Cookies.Add(new HttpCookie("RespId") {
		Value = DateTime.Now.ToString("mmssfff")
	});
}
</script>

.NET Framework

WebClient 用起來最簡便但不支援 CookieContainer,我們可透過繼承技巧擴充它。 CookieContainer 加入 Cookie 時記得要指定 Domain,WebClient 才知道連哪個站台要附帶該 Cookie。取回 Cookie 時也要指定 Uri,以便取出屬於該網站的 Cookie:

using System;
using System.Net;

namespace WebClientWithCookie
{
    internal class Program
    {
        static void Main(string[] args)
        {
            var wc = new CookieWebClient();
            var url = "http://localhost/aspnet/CookieTest/AutoRedirect.aspx";
            wc.CookieContainer.Add(new Cookie
            {
                Name = "ReqId",
                Value = DateTime.Now.ToString("mm:ss.fff"),
                Domain = new Uri(url).Host
            });
            Console.WriteLine(wc.DownloadString(url));
            Console.WriteLine($"RespId=" + wc.CookieContainer.GetCookies(new Uri(url))["RespId"]?.Value);
            Console.ReadLine();
        }
    }

    public class CookieWebClient : WebClient
    {
        public CookieContainer CookieContainer { get; set; } = new CookieContainer();
        protected override WebRequest GetWebRequest(Uri address)
        {
            var webReq = base.GetWebRequest(address);
            var httpWebReq = webReq as HttpWebRequest;
            if (httpWebReq != null) httpWebReq.CookieContainer = CookieContainer;
            return webReq;
        }
    }
}

實測結果:

.NET 6

.NET Core / .NET 6 建議改用 HttpClient,一樣是用 CookieContainer。先建立 HttpClientHandler 設定傳輸屬性,其中包含 CookieContainer 屬性,用 HttpClientHandler 做為 HttpClient 的建構參數,其餘寫法與 .NET Framework 大同小異。

var handler = new HttpClientHandler();
var url = "http://localhost/aspnet/CookieTest/AutoRedirect.aspx";
handler.CookieContainer.Add(new System.Net.Cookie
{
    Name = "ReqId",
    Value = DateTime.Now.ToString("mm:ss.fff"),
    Domain = new Uri(url).Host
});
var client = new HttpClient(handler);
var response = await client.GetAsync(url);
Console.WriteLine(response.Content.ReadAsStringAsync().Result);
Console.WriteLine($"RespId=" + handler.CookieContainer.GetCookies(new Uri(url))["RespId"]?.Value);

實測成功:

PowerShell

PowerShell 一樣是靠 CookieContainer。使用時先建立 WebRequestSession,其餘操作與 .NET 相同。

$url = "http://localhost/aspnet/CookieTest/AutoRedirect.aspx"
$sess = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$cookie = New-Object System.Net.Cookie
$cookie.Name = "ReqId"
$cookie.Value = [System.DateTime]::Now.ToString("mm:ss.fff")
$cookie.Domain = (New-Object Uri($url)).Host
$sess.Cookies.Add($cookie)

(Invoke-WebRequest $url -WebSession $sess).Content
"RespId=" + $sess.Cookies.GetCookies((New-Object Uri($url)))["RespId"].Value

測試 OK。

Samples for sending and receiving cookies with .NET WebClient, HttpClient and PowerShell.


Comments

Be the first to post a comment

Post a comment