MVC 5中无法在一个控制器访问另一个控制器的Session值
看起来你碰到了MVC里登录后存Session,换个控制器就拿不到值的坑,我之前也踩过类似的,给你梳理几个常见的排查方向和解决办法:
1. 先确认Session状态的配置是否正确
先检查web.config里有没有启用Session状态,默认MVC是开着的,但如果有配置改动可能会出问题。确保这段配置存在:
<system.web> <sessionState mode="InProc" timeout="20" /> <!-- InProc是开发环境默认模式,够用 --> </system.web>
要是你用的是更复杂的Session存储模式(比如StateServer),还要确认对应的服务是否正常运行。
2. 检查控制器的基类是否正确
如果你的目标控制器是Web API控制器(继承ApiController),默认是不支持Session的!Web API需要额外配置才能启用:
- 先在
Global.asax的Application_Start里加这段:
GlobalConfiguration.Configuration.Services.Add(typeof(IHttpModule), new SessionAuthenticationModule());
- 然后在Web API控制器的方法上添加属性,根据需求选:
[SessionState(SessionStateBehavior.Required)] // 需要读写Session // 或者 [SessionState(SessionStateBehavior.ReadOnly)] // 只读Session
如果是普通MVC控制器,一定要确保继承的是System.Web.Mvc.Controller,这个基类默认支持Session。
3. 换用控制器自带的Session属性,别直接用HttpContext.Current
你代码里用了System.Web.HttpContext.Current.Session,在异步方法或者某些上下文里这个对象可能为空。建议改成控制器自带的Session属性,更可靠:
// 在AccountController的登录方法里这么写 Member member = dbContextRead.Members.Include(m => m.Location).SingleOrDefault(e => e.AspNetUserId == user.Id); Session["member"] = member; Session["location"] = member.Location;
4. 确认你的实体类是可序列化的
Session存储对象时,要求对象必须可序列化,不然存进去也读不出来。给Member和Location类加上[Serializable]特性:
[Serializable] public class Member { // 你的属性 public Location Location { get; set; } } [Serializable] public class Location { // Location的属性 }
如果有循环引用的导航属性,可能还需要额外处理,但普通实体类加这个特性基本就能解决问题。
5. 检查登录后的跳转逻辑有没有清空Session
要是登录后用了Response.Redirect或者RedirectToAction,一定要确保Session写入是在跳转之前执行的,而且中间没有不小心清空Session的代码。另外用Forms Authentication的话,别在登录后手动重置Session。
6. 排查Session是否被回收了
如果用的是InProc模式,应用池回收、网站重启甚至开发环境下修改代码导致应用重启,都会让Session丢失。可以先测试:登录后立即在AccountController里读取Session,看能不能拿到值。如果可以,那大概率是后续操作或者环境重启导致Session丢了。
内容的提问来源于stack exchange,提问作者Andrei dela Cruz

