由於 HTTP 是無狀態的通訊協定,如果沒有額外處理,每次請求都會是獨立的,沒辦法保留來自客戶端的資料。今天會介紹要怎麼在應用程式中儲存或暫存資料跟狀態。
開發人員可以由幾個面向來判斷需要使用哪種狀態管理的方式:
ASP.NET Core 框架中好幾種方式來管理狀態,包括:
Cookie 以類似 key-value 的資料結構儲存在客戶端,會隨著每次請求被傳送到伺服器端,所以當 Cookie 數量增加或儲存的值長度較大的時候,請求的封包會隨之變大。由於在客戶端可以新增、修改或刪除 Cookie,不建議將敏感資料以這個方式儲存,或者要加密後再儲存。在 Controller 中以下列程式來讀寫 Cookie:
public class ApplicationStatesController : Controller
{
    public IActionResult Cookie()
    {
        Request.Cookies.TryGetValue("SampleCookie", out var cookieValue);
        // 把取出的值寫進 log
        _logger.LogDebug(cookieValue);
        Response.Cookies.Append("SampleCookie", Guid.NewGuid().ToString(), new CookieOptions
        {
            MaxAge = TimeSpan.FromMinutes(30)
        });
        return new EmptyResult();
    }
}
Response.Cookies.Append 的第三個參數是可選的 CookieOptions 類別,用來設定相關參數。範例中是將 SampleCookie 的值設定為 30 分鐘後過期。執行後可以在瀏覽器的開發工具中看到當前網域的所有 cookie。
在其他地方可能會翻譯成「工作階段」。Session 是將資料存在伺服器的記憶體或資料庫中,再把一個唯一識別值 (id) 寫到 Cookie 中,並透過此 id 來存取資料。
要使用 Session 的設定比 Cookie 麻煩很多,需要在 Startup.cs 中設定:
Session 儲存區的 IDistributedCache。目前提供記憶體、資料庫和 Redis 三種儲存方式。Startup.ConfigureServices 中呼叫 AddSession。Startup.Configure 中呼叫 UseSession。public class Startup
{
    public void ConfigureServices(IServiceCollection services){
        // ...other services configurations
        services.AddDistributedMemoryCache();
        services.AddSession();
    }
    public void Configure(IApplicationBuilder app)
    {
        // ...other middlewares registrations
        app.UseSession();
        // ...other middlewares registrations
    }
}
需要特別注意加入中介層的順序,如果在 UseSession 之前先呼叫 UseMvc,就沒辦法在 MVC 架構中的程式使用 Session。設定完成後就可在應用程式中用 SessionExtensions 提供的各種方法來讀寫 Session 值。由於 Session 儲存在 IDistributedCache 中,資料都需要轉換成 byte[],只有另外提供 string 和 int32 的介面做讀寫。如果要儲存物件,就需要序列化成字串來處理。官方文件中有提供序列化的擴充方法可以參考:
public static class SessionSerializerExtensions
{
    public static void Set<T>(this ISession session, string key, T value)
    {
        session.SetString(key, JsonConvert.SerializeObject(value));
    }
    public static T Get<T>(this ISession session, string key)
    {
        var value = session.GetString(key);
        return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
    }
}
在程式中讀寫的方式:
public IActionResult Session()
{
    var sessionValue = HttpContext.Session.GetString("SampleSession");
    HttpContext.Session.SetInt32("Year", 2018);
    HttpContext.Session.Set("CurrentDate", DateTime.Now);
    return new EmptyResult();
}
今天就先講到這吧~明天再來談談其他儲存狀態的方式