我正在构建一个大致遵循存储库模式的应用程序,顶部有一个服务层,类似于Conery的MVC Storefront的早期版本。
我需要实现一个返回除当前用户之外的所有用户的页面。我已经在存储库和服务层上有GetUsers()方法,所以问题是在哪里应用“除了当前用户。”
服务层是否应该知道HttpContext,从而应用此规则?我很想将当前用户(id)从控制器传递给这个服务方法,但是如果服务层能够识别HttpContext并且可以自己完成,那么它似乎更清晰。
一个明显的选择是直接在Controller中应用此规则,但我对这个想法并不热衷......
编辑 - 只是为了回答评论:我看到了反向依赖问题的问题,这是我完全忽视的问题。我将Mehrdad作为回答原因,但是每个人都真的提供了值得阅读的有价值的回应!
答案 0 :(得分:18)
绝对不是。我在设计这类事物时的心态是这样的:我假设我需要编写一个基于Windows的应用程序以及Web应用程序,并尽量减少对Web特定内容的依赖。直接传递HttpContext
会增加服务层与Web UI层的耦合,这是不理想的。
答案 1 :(得分:9)
答案是,否。
服务层不仅不依赖于当前的表示层,我认为它应该不依赖于当前的应用程序。例如,我不会将自定义AppContext
类用作JonoW建议的here。
相反,将当前用户作为参数传递给GetAllUsersExceptForTheCurrentUser
方法。这样,任何需要处理用户的应用程序都可以使用该服务,而不仅仅是当前应用程序。
答案 2 :(得分:4)
您应该不在服务层和Web层之间创建反向依赖关系。考虑当您希望扩展服务层以使用基于表单的应用程序或Windows服务时会发生什么。现在,您必须解决Web依赖关系,以使相同的方法工作或复制一些(可能是小的,但仍然重复)代码。您可以更好地将用户的标识符提取到服务层上下文中有用的内容中,并将该值与服务层一起使用。在网站上处理过滤也是可以接受的,但如果你不止一次这样做,就需要将其重构为一个公共场所,服务层就是它的自然场所。
答案 3 :(得分:2)
我发现构建一个包含我当前用户对象(以及其他上下文数据)的自定义AppContext类是一个好习惯。该类没有对System.Web的引用。任何需要上下文感知的服务方法都应该有一个AppContext参数(例如,用于检查安全权限,或者按照您的情况获取当前用户)。如果需要,在Web层中填充此对象并将其保留在会话中。这样,您的服务层对System.Web一无所知。
答案 4 :(得分:1)
没有。这样做会使您的代码更难以测试和重复使用。
我倾向于为这种事物构建一个基础设施接口(称之为IAuthentication或其他东西),并在其上公开一个CurrentUser属性。然后我通过它的构造函数将它注入我的服务中。即公共MyService(IAuthentication auth)
最后,您可以构建一个支持HutpContext的IAuthentication实现(比如WebAuthentication)。
现在,当您创建服务时,您也可以创建其依赖项:
var myService = new MyService(new WebAuthentication());
var otherUsers = myService.GetAllOtherUsers();
如果你使用的是IoC容器,丑陋的依赖甚至可能会消失!