调用HttpContext.Session.GetString()报对象引用错误解决方法
问题原因
抛出“非静态方法、对象或属性需要对象引用”错误,是因为直接以静态调用的方式使用了HttpContext。HttpContext是和单次HTTP请求生命周期绑定的实例对象,既不能直接通过new关键字创建,也不能脱离当前请求上下文直接静态访问,需要根据代码所在位置,用对应方式获取有效实例。
不同场景的正确获取方式
1. 在Controller、Razor Page模型类中使用
Controller、PageModel基类已经内置了当前请求关联的HttpContext属性,直接调用即可,不需要额外配置:
public class CartController : Controller { public string GetUserCartId() { // 直接调用基类的HttpContext实例读取Session var cartId = HttpContext.Session.GetString("CartId"); // 首次访问无CartId时可生成后写入Session if (string.IsNullOrEmpty(cartId)) { cartId = Guid.NewGuid().ToString(); HttpContext.Session.SetString("CartId", cartId); } return cartId; } }
2. 在自定义服务、业务逻辑类中使用
如果是在分层架构的业务层、仓储层等非Controller类中读取Session,需要通过依赖注入获取IHttpContextAccessor实例,再通过它拿到当前请求的HttpContext。
第一步:提前在Program.cs中注册必要服务和中间件
注意中间件顺序不能错乱,UseSession必须放在路由、授权、端点映射中间件之前,否则Session无法正常读取:
var builder = WebApplication.CreateBuilder(args); // 注册Session服务 builder.Services.AddSession(options => { options.IdleTimeout = TimeSpan.FromMinutes(30); options.Cookie.HttpOnly = true; options.Cookie.IsEssential = true; }); // 注册HttpContext访问器,供非Controller类获取上下文 builder.Services.AddHttpContextAccessor(); // 注册你的业务服务 builder.Services.AddScoped<CartService>(); // 注册MVC相关服务 builder.Services.AddControllersWithViews(); var app = builder.Build(); // 配置中间件管道 app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); // UseSession必须放在UseRouting之后、UseAuthorization和端点映射之前 app.UseSession(); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
第二步:在自定义类中通过构造函数注入IHttpContextAccessor
public class CartService { private readonly IHttpContextAccessor _contextAccessor; // 依赖注入框架会自动传入IHttpContextAccessor实例 public CartService(IHttpContextAccessor contextAccessor) { _contextAccessor = contextAccessor; } public string GetCurrentUserCartId() { var httpContext = _contextAccessor.HttpContext; // 非请求上下文(比如后台任务、系统启动阶段)下HttpContext为null,需要做判空处理 if (httpContext == null) { throw new InvalidOperationException("仅在HTTP请求处理流程中可读取用户CartId"); } var cartId = httpContext.Session.GetString("CartId"); if (string.IsNullOrEmpty(cartId)) { cartId = Guid.NewGuid().ToString(); httpContext.Session.SetString("CartId", cartId); } return cartId; } }
避坑提示
- 不要自行
new HttpContext实例,手动创建的对象没有绑定真实的请求连接、Cookie、Session等数据,完全无法正常使用。 - 不要在静态变量、单例服务中长期存储
HttpContext实例,请求结束后相关对象会被框架释放,会引发对象已释放异常、内存泄漏等问题。 - 后台定时任务、异步脱离请求线程的执行场景中,不存在有效HTTP上下文,
IHttpContextAccessor.HttpContext会返回null,这种场景不要尝试读取Session,应该在发起后台任务时就把需要的CartId作为参数传入。
内容的提问来源于stack exchange,提问作者Abdullah Khan
相关产品推荐
相关产品推荐

