.NET Core 3 MVC分层项目中如何在服务层获取Session值
解决.NET Core 3 MVC服务层获取Session值的问题
首先得明确:服务层作为独立类库,不应该直接依赖Web层的HttpContext——这会破坏分层架构的解耦原则,也是你直接用HttpContext失败的核心原因(服务层没有访问控制器HttpContext的权限,也不该有)。下面给你两种可行的方案,优先推荐第一种:
方案一:控制器传递Session值到服务层(推荐)
既然你的控制器已经能轻松拿到Session里的UserID和RoleName,最直接且符合架构设计的做法是把这些值传递给服务层,而非让服务层自己去拿。
步骤1:修改服务层,添加参数或属性接收值
比如给ContactService加个RoleName属性,或者在业务方法里接收参数:
namespace CRM.Service.Services.ContactService { public class ContactService : IRepository<Contact>, IDisposable { public int UserID { get; set; } public string RoleName { get; set; } // 新增属性 private readonly _DbContext _context; private readonly IMapper _mapper; public ContactService(_DbContext context, AutoMapperConfig autoMapperConfig) { _context = context; _mapper = autoMapperConfig.Mapper; } // 或者在业务方法里直接接收参数 public IEnumerable<Contact> GetUserContacts(int userId, string roleName) { // 根据userId和roleName做数据库查询 return _context.Contacts.Where(c => c.CreatedBy == userId).ToList(); } } }
步骤2:在控制器中传递值
你可以在控制器构造时给服务层的属性赋值,或者调用方法时传入参数:
namespace CRM.Web.Controllers { [Authorize] public class ContactController : Controller { private int UserID { get { return Convert.ToInt32(HttpContext.Session.GetInt32("UserID")); } } private string RoleName { get { return HttpContext.Session.GetString("RoleName"); } } private readonly ContactService _contactService; public ContactController(ContactService contactService) { _contactService = contactService; // 构造时给服务层赋值 _contactService.UserID = UserID; _contactService.RoleName = RoleName; } public IActionResult Index() { // 或者调用方法时直接传参 var contacts = _contactService.GetUserContacts(UserID, RoleName); return View(contacts); } } }
这种方式的好处是完全解耦了服务层和Web层,服务层不需要知道Session的存在,只专注于业务逻辑,测试起来也更方便。
方案二:通过IHttpContextAccessor注入(不推荐,仅作备选)
如果因为某些原因必须让服务层直接获取Session,可以通过IHttpContextAccessor来实现,但这会增加服务层与Web层的耦合度,降低可测试性。
步骤1:在Startup.cs中注册服务
在ConfigureServices方法里添加:
services.AddHttpContextAccessor();
步骤2:在服务层注入IHttpContextAccessor
修改ContactService的构造函数,注入并使用:
namespace CRM.Service.Services.ContactService { public class ContactService : IRepository<Contact>, IDisposable { private readonly _DbContext _context; private readonly IMapper _mapper; private readonly IHttpContextAccessor _httpContextAccessor; public ContactService(_DbContext context, AutoMapperConfig autoMapperConfig, IHttpContextAccessor httpContextAccessor) { _context = context; _mapper = autoMapperConfig.Mapper; _httpContextAccessor = httpContextAccessor; } public int UserID { get { return Convert.ToInt32(_httpContextAccessor.HttpContext?.Session.GetInt32("UserID") ?? 0); } } public string RoleName { get { return _httpContextAccessor.HttpContext?.Session.GetString("RoleName") ?? string.Empty; } } } }
注意这里要加空值判断,避免HttpContext为null时抛出异常。
总结
优先选择方案一,它更符合分层架构的设计思想,让服务层保持独立和可复用性。方案二仅作为特殊场景下的备选,尽量少用。
内容的提问来源于stack exchange,提问作者Hamza Ali
相关产品推荐
相关产品推荐

