You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 09:27:49