.NET 6中传递ISession至类库及跨控制器会话丢失问题
有两种可行方案:
方案1:安装正确的NuGet包
类库中不要安装Microsoft.AspNetCore.Http.Features,改为安装Microsoft.AspNetCore.Http包。GetString/SetString是这个包中ISession的扩展方法,安装后直接就能调用,无需额外封装。注意要保证包的版本和你的ASP.NET Core项目版本一致,避免兼容性问题。
方案2:自行封装扩展方法
如果不想依赖Microsoft.AspNetCore.Http包,可手动实现字符串操作的扩展方法:
using System.Text; using Microsoft.AspNetCore.Http.Features; public static class SessionExtensions { public static void SetString(this ISession session, string key, string value) { if (session == null) throw new ArgumentNullException(nameof(session)); if (key == null) throw new ArgumentNullException(nameof(key)); session.Set(key, Encoding.UTF8.GetBytes(value)); } public static string GetString(this ISession session, string key) { if (session == null) throw new ArgumentNullException(nameof(session)); if (key == null) throw new ArgumentNullException(nameof(key)); var data = session.Get(key); return data == null ? null : Encoding.UTF8.GetString(data); } }
将这个类放在类库中,使用时直接调用扩展方法即可,和框架自带的用法完全一致。
控制器会话共享规则
默认情况下,同一个用户的请求只要携带相同的会话Cookie(默认名为.AspNetCore.Session),所有控制器共用同一个会话。会话的标识由Cookie中的会话ID决定,只要Cookie有效且能被正确传递,跨控制器的会话数据就是共享的。
会话数据丢失的常见原因及解决
未提交会话修改:修改会话数据后,必须调用
session.CommitAsync()(或同步的session.Commit())来持久化数据。尤其是在类库中操作会话后,一定要执行提交操作,否则服务器不会保存修改后的会话数据。会话Cookie配置问题:检查
Startup.cs或Program.cs中的会话配置,确保Cookie的SameSite、Path、Domain等设置正确,避免浏览器在跨控制器请求时拒绝携带会话Cookie。例如:
builder.Services.AddSession(options => { options.Cookie.SameSite = SameSiteMode.Lax; options.Cookie.Path = "/"; options.IdleTimeout = TimeSpan.FromMinutes(30); });
会话存储配置错误:如果使用内存存储(默认),服务器重启会丢失所有会话数据,但切换控制器不会导致丢失。若需要持久化会话,可配置分布式缓存(如Redis、SQL Server)。
会话ID意外变更:检查浏览器是否禁用了Cookie,或者请求的域名/端口不一致,导致每次请求生成新的会话ID,原有会话数据无法被访问。
内容的提问来源于stack exchange,提问作者Sonnich Jensen

