[ASP.NET Core 6 MVC] 使用 Session
這篇是參考自 C# Corner : How To Use Sessions In ASP.NET Core 的教學,不過文中是 .NET 5,所以和 .NET 6 設定上有點差異,再加上和過去 .NET 4 使用 namespace 後就可以無腦使用 Session 不太一樣,就做了這個筆記,以下範例使用 Visual Studio 2022,建立專案為 ASP.NET Core Web 應用程式 (Model-View-Controller)使用 .NET 6.0 架構。
下載 Session 套件
在方案總管視窗對「相依性(Dependencies)」滑鼠右鍵,選擇「管理 NuGet 套件」:
在「瀏覽」標籤頁中搜尋「Session」,應該最多人下載的是 Microsoft 的「Microsoft.AspNetCore.Session」:
依版本點選「安裝」(這裡我選最新穩定版 2.2.0):
若有變更警告點選「OK」,授權提示點選「I Accept」:
裝好後剛剛的頁面應該會顯示目前版本,且原本的「安裝」變成「解除安裝」,就可以關掉 NuGet 分頁了。
設定 Program.cs
再來要設定 Program.cs 設定檔,至方案總管視窗雙擊此檔案:
原本檔案的最上面是:
var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllersWithViews(); var app = builder.Build();
在此給容器加入 Session service:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddDistributedMemoryCache(); // 加入記憶體供 Session 使用
builder.Services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(1); // 設定 Session Expire 時間
});
var app = builder.Build();
app.UseSession(); // 加人 pipe line
使用 Session ,存取字串和整數
要利用 Session 存取字串可以使用 SetString() 和 GetString() 方法,而存取整數的是 SetInt32() 和 GetInt32(),方法在 HttpContext.Session 下,例如下面我用範本的 Home/Privacy 與 Home/ 兩個 Action 和 View,在 HomeController.cs 中的這兩個 Action 中加入以下程式碼:
namespace DemoSession.Controllers
{
public class HomeController : Controller
{
public IActionResult Privacy()
{
// 將這兩個值存入 Session,key 分別為 "Greeting" 和 ".NET"
HttpContext.Session.SetString("Greeting", "Hello World!!!");
HttpContext.Session.SetInt32(".NET", 6);
return View();
}
public IActionResult Index()
{
// 從 Session 中用 key 取出數值,賦值給 ViewBag 帶往 View 去
ViewBag.Message = HttpContext.Session.GetString("Greeting");
ViewBag.Version = HttpContext.Session.GetInt32(".NET");
return View();
}
}
}
而 Index 的 View 加入從 ViewBag 取出的值:
<p>
@ViewBag.Message <!-- 顯示從 Session 取出的字串 -->
</p>
<p>
此版本為 .NET @ViewBag.Version <!-- 顯示從 Session 取出的整數 -->
</p>
執行應用程式,route 預設打開 Home/Index,會看到因為 ViewBag 的兩個變數都是空的,所以呈現缺項的檢視頁面:
如果點選範本提供的上方 Layout 中的「Privacy」連結,經過 Controller 的 Action 看到的 Privacy View :
檢視頁面沒有東西,因為我們也沒有修改他,點擊此頁是為了測試經過 Privacy 的 Action 時會做的,也就是將變數存入 Session ,這時再點擊上方的「Home」連結回到 Home/Index:
就會看到 Home/Index 出現 ViewBag 的兩個變數了,會有這兩個變數的原因是因為剛剛走過 Privacy 的 Action,在 Session 存入變數,然後在 Index 的 Action 從 Session 取出變數,賦予給 ViewBag ,使 Index 的 View 能夠呈現。
- HttpContext.Session.SetString(key, value) 存入字串
- HttpContext.Session.GetString(key) 取出字串
- HttpContext.Session.SetInt(key, value) 存入整數
- HttpContext.Session.GetInt(key) 取出整數
用 Json 序列化使 Session 存取物件
如果要存入 Session 的不只是字串和整數,可以利用 Newtonsoft 的 Json 序列化,首先要在 NuGet 管理套件下載 Newtonsoft.Json:
引用 Newtonsoft.Json 命名空間後,可使用 JsonConvert.SerializeObject(物件) 將物件轉成字串,使用 JsonConvert.DeserializeObject<類別>(字串) 將字串轉成相對應的物件。為了示範物件轉換,我在 ~/Models 寫了一個 Student.cs 類別,有字串、浮點數、日期的屬性與建構子:
namespace DemoSession.Models
{
public class Student
{
public string Name { get; set; }
public double Height { get; set; }
public string Major { get; set; }
public DateTime Birthday { get; set; }
public Student(string name, double height, string major, DateTime birthday)
{
Name = name;
Height = height;
Major = major;
Birthday = birthday;
}
}
}
而 HomeController.cs 在 Privacy Action 實體化一個 List,新增四個 Student 物件,將他序列化放進 Session 中,而 Index Action 將資料從 Session 取出來,一個是字串給 ViewBag.StudentsString,另一個反序列化轉回 List 物件,為了處理空值有一些判斷,但不是這篇的重點,轉成物件給 ViewBag.StudentObject:
using DemoSession.Models;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace DemoSession.Controllers
{
public class HomeController : Controller
{
public IActionResult Privacy()
{
// 實體化集合物件
List<Student> students = new List<Student>();
students.Add(new Student("May", 158.5, "ComputerScience", new DateTime(2005,5,5)));
students.Add(new Student("Johnny", 184.0, "Mathematics", new DateTime(1997, 10, 24)));
students.Add(new Student("Eddie", 181.0, "Biology", new DateTime(2000, 1, 28)));
students.Add(new Student("Venom", 179.5, "Mathematics", new DateTime(1999, 7, 12)));
// 將物件序列化成字串,以 "stuList" 為 key 存到 Session 中
HttpContext.Session.SetString("stuList", JsonConvert.SerializeObject(students));
return View();
}
public IActionResult Index()
{
// 從 Session 以 "stuList" 為 key 取出字串資料
string StudentsString = HttpContext.Session.GetString("stuList");
ViewBag.StudentsString = StudentsString;
// 若不為空值,將字串反序列化回集合物件
ViewBag.StudentsObject = string.IsNullOrEmpty(StudentsString) ?
null : JsonConvert.DeserializeObject<List<Student>>(StudentsString);
return View();
}
}
}
Index 的檢視中,將 Controller 帶過去的 ViewBag 資料顯示出來,一個是字串的 ViewBag.StudentsString,另一個是確定非空時用 foreach 遍尋出來用表格呈現的 ViewBag.StudentsObject,兩者都是來自 Session。index.cshtml 程式碼如下:
<p>
字串資料: @ViewBag.StudentsString
</p>
<p>
<table class="table table-striped">
<tr>
<th>Name</th>
<th>Height</th>
<th>Major</th>
<th>Birthday</th>
</tr>
@{
if(ViewBag.StudentsObject != null)
{
foreach(Student student in ViewBag.StudentsObject)
{
<tr>
<td>@student.Name</td>
<td>@student.Height</td>
<td>@student.Major</td>
<td>@student.Birthday</td>
</tr>
}
}
}
</table>
</p>
執行應用程式,先到 Home/Index 是沒有東西的,此時 Session 還沒有資料:
點擊 Home/Privacy 再回到 Home/Index 就會因為 Session 有資料,使得 List<Student> 物件以表格呈現,成功在 Session 傳遞物件:
- Newtonsoft.Json.JsonConvert.SerializeObject(object) 序列化物件成字串
- Newtonosft.Json.JsonConvert.DeserializeObject<class>(string) 反序列化成物件
將序列化寫成擴充方法
可以將以上序列化及反序列化的方法寫成 HttpContext.Session 的靜態擴充方法,在專案新增一個資料夾 ~/Extensions/,新增一個類別 SessionExtension.cs,程式碼:
using Newtonsoft.Json;
namespace DemoSession.Extensions
{
public static class SessionExtension
{
public static void SetObject<T>(this ISession session, string key, T value)
{
session.SetString(key, JsonConvert.SerializeObject(value));
}
public static T GetObject<T>(this ISession session, string key)
{
var value = session.GetString(key);
return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value);
}
}
}
使用時就可直接 HttpContext.Session.SetObject<>() 與 GetObject<>():
using DemoSession.Models;
using DemoSession.Extensions;
namespace DemoSession.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
// 從 Session 中用 "stuList" 的 key 取出物件
ViewBag.StudentsObject = HttpContext.Session.GetObject<List<Student>>("stuList");
return View();
}
public IActionResult Privacy()
{
List<Student> students = new List<Student>();
students.Add(new Student("May", 158.5, "ComputerScience", new DateTime(2005,5,5)));
students.Add(new Student("Johnny", 184.0, "Mathematics", new DateTime(1997, 10, 24)));
students.Add(new Student("Eddie", 181.0, "Biology", new DateTime(2000, 1, 28)));
students.Add(new Student("Venom", 179.5, "Mathematics", new DateTime(1999, 7, 12)));
// 將物件以 "stuList" 的 key 存入 Session
HttpContext.Session.SetObject<List<Student>>("stuList", students);
return View();
}
}
}
可更簡潔存取 Session 中的物件。













留言
張貼留言