如何在非代码后置类文件security.cs中访问Session变量?
首先咱们得先捋清楚为啥会抛出NullReferenceException——大概率不是Session本身不能被访问,而是HttpContext.Current在你调用security.cs代码的场景下是null(比如在后台线程、非请求上下文的代码里执行),或者Session["user"]还没被赋值就被提前调用了。下面给你几个不用大量修改代码的可行方案:
方案1:确保调用时机处于请求上下文内
如果你的security.cs方法是在ASP.NET请求生命周期内被触发的(比如页面事件、接口调用流程里),先检查是不是调用时机不对——比如在Session["user"]还没在default.aspx.cs里赋值时,就提前执行了security.cs的代码。
如果是请求上下文外的场景(比如定时任务、异步后台线程),HttpContext.Current本来就是null,这时候可以选两个轻量改动的方向:
- 少数调用场景的话,在调用
security.cs方法前先把Session["user"]的值取出来,作为参数传入(虽然你不想大量改,但这个方案最稳妥,不会引入额外依赖); - 把用户信息存到
HttpRuntime.Cache静态缓存里,同时绑定Session的End事件来清理缓存,避免内存泄漏。
方案2:给security.cs添加上下文预存(最小改动版)
不想传参数的话,可以给security.cs加个静态字段存储请求上下文,让调用方在请求内先把上下文传进去,后续方法就能直接用:
public class security { // 静态字段暂存当前请求上下文 private static HttpContext _currentRequestContext; // 在请求开始时调用(比如default.aspx.cs的Page_Load里) public static void InitRequestContext(HttpContext context) { _currentRequestContext = context; } public void YourBusinessMethod() { // 加空值判断避免异常 if (_currentRequestContext?.Session?["user"] != null) { string sUser = _currentRequestContext.Session["user"].ToString(); // 你的业务逻辑 } else { // 处理Session为空的边界情况 } } }
然后在default.aspx.cs的Page_Load里先执行security.InitRequestContext(this.Context);,后续security.cs里的方法就能直接用预存的上下文访问Session了,不用每个方法都传参数。
方案3:用HttpContextAccessor(.NET Framework 4.7.2+适用)
如果你的项目升级到了.NET Framework 4.7.2及以上,可以用System.Web.HttpContextAccessor来优雅获取上下文,不用手动传递:
- 先在
Global.asax的Application_Start里注册:
using System.Web; using System.Web.Mvc; protected void Application_Start() { // 注册HttpContextAccessor到依赖容器 DependencyResolver.Current.Register(typeof(IHttpContextAccessor), () => new HttpContextAccessor()); }
- 然后在
security.cs里直接获取上下文:
public class security { public static string GetCurrentUser() { var contextAccessor = DependencyResolver.Current.GetService<IHttpContextAccessor>(); return contextAccessor?.HttpContext?.Session?["user"]?.ToString(); } // 你的其他业务方法 }
这个方法不用手动传递上下文,只要在请求内调用,就能拿到正确的Session,改动量极小。
方案4:检查Session配置是否被改动
升级后可能web.config里的Session配置被意外修改了,比如mode设成了Off或者超时时间过短,导致Session提前失效。可以检查web.config的Session节点:
<system.web> <sessionState mode="InProc" timeout="20" /> <!-- 确保mode不是Off --> </system.web>
另外也可以在default.aspx.cs赋值Session["user"]后加个日志,确认值确实被成功设置了,排除赋值逻辑被母版页的重定向、异常中断等情况跳过的可能。
最后提醒下:不管用哪种方案,都要养成加空值判断的习惯(比如用?.ToString()),从根源上避免空引用异常。
内容的提问来源于stack exchange,提问作者user6635509

