Asp.net mvc 服务层应该访问HttpContext吗?

Asp.net mvc 服务层应该访问HttpContext吗?,asp.net-mvc,design-patterns,Asp.net Mvc,Design Patterns,我正在构建一个大致遵循存储库模式的应用程序,上面有一个服务层,类似于Conry的MVC Storefront的早期版本 我需要实现一个返回除当前用户之外的所有用户的页面。我在存储库和服务层上已经有了GetUsers()方法,所以问题是在哪里应用“除了当前用户之外” 服务层是否应该知道HttpContext,从而应用此规则?我很想把当前用户(id)从控制器传递到这个服务方法,但是如果服务层是HttpContext感知的,并且可以自己完成这项工作,那么看起来就更干净了 一个明显的选择是直接在控制器中

我正在构建一个大致遵循存储库模式的应用程序,上面有一个服务层,类似于Conry的MVC Storefront的早期版本

我需要实现一个返回除当前用户之外的所有用户的页面。我在存储库和服务层上已经有了GetUsers()方法,所以问题是在哪里应用“除了当前用户之外”

服务层是否应该知道HttpContext,从而应用此规则?我很想把当前用户(id)从控制器传递到这个服务方法,但是如果服务层是HttpContext感知的,并且可以自己完成这项工作,那么看起来就更干净了

一个明显的选择是直接在控制器中应用这个规则,但我对这个想法不感兴趣



编辑-只是对答案进行评论:我看到了反向依赖问题的问题,这是我完全忽略的问题。我将Mehrdad的答案标记为到期投票,但每个人都提供了一个非常有价值的答案,值得一读

绝对不是。我在设计这类东西时的心态是这样的:我假设我需要在Web应用程序中编写一个基于Windows的应用程序,并尽量减少对Web特定内容的依赖。直接传递
HttpContext
将增加服务层与Web UI层之间的耦合,这并不理想。

您应该不要在服务层和Web层之间创建反向依赖关系。考虑当您想扩展服务层以使用基于表单的应用程序或Windows服务时会发生什么。现在,您必须处理web依赖关系,以使相同的方法工作或复制一些(可能很小,但仍然是重复的)代码。您最好将用户标识符提取到服务层上下文中有用的内容中,并将该值用于服务层。在网站上处理过滤也是可以接受的,但如果您多次这样做,则需要将其重构到一个公共位置,并且服务层是它的自然位置。

我发现构建包含当前用户对象(以及其他上下文数据)的自定义AppContext类是一个很好的做法。此类没有对System.Web的引用。任何需要上下文感知的服务方法都应该有一个AppContext参数(例如,用于检查安全权限,或获取当前用户,如您的情况)。在web层中填充此对象,并在需要时使其保持会话状态。这样,您的服务层对System.Web一无所知

答案是,

在我看来,服务层不仅应该不依赖于当前的表示层,而且应该不依赖于当前的应用程序。例如,我不会像建议的那样使用自定义的
AppContext


相反,将当前用户作为参数传递给
GetAllUsersExceptForTheCurrentUser
方法。这样,需要处理用户的任何应用程序都可以使用该服务,而不仅仅是当前应用程序。

否。这样做会使代码更难测试和重用

我倾向于为这类事情构建一个基础架构接口(称之为IAAuthentication或其他东西),并在其上公开CurrentUser属性。然后我会通过构造函数将其注入到我的服务中。i、 e.公共MyService(IAAuthentication-auth)

最后,您可以构建一个支持HttpContext的IAAuthentication实现(比如WebAuthentication)

现在,当您创建服务时,也会创建其依赖项:

var myService = new MyService(new WebAuthentication());
var otherUsers = myService.GetAllOtherUsers();

如果您使用的是IoC容器,丑陋的依赖甚至可以消失

一点问题都没有,我只是喜欢以同样的方式对待所有上下文感知的情况。我喜欢这个想法,JonoW!我现在可能只是传递id,如果/当我的服务方法开始变得带有参数和重载时,这将非常好。我甚至可以在实例化服务对象时传递AppContext,从而满足我的愿望,使服务具有某种“感知”,但不依赖于System.Web。谢谢:)我想这确实取决于需要感知上下文的服务方法的数量。在我们当前的项目中,它们都是,因为每个服务方法都有不同的安全限制(由属性定义),所以每个服务方法调用都需要查看当前用户的角色,以检查是否允许他们调用此方法。但这可能太过分了!如果参数的数量有问题,只需将它们封装在某个类/结构中即可。没有必要使它们面向上下文。同意。特别是,当您需要将服务层置于负载平衡器之后时,您会感谢自己没有将上下文和状态添加到服务层。让我重新考虑我对JonoW建议的最初反应。我明白你们的意思,但当我说一个服务方法需要上下文感知时,我的意思是有一个服务方法需要知道谁在调用它。例如,你们是如何处理授权的?i、 例如,确定是否允许方法调用方调用该方法?我在这个领域有点新手,所以很想听听别人是怎么做的/什么是最佳实践。为“单一责任校长”喝彩。一个方法应该完成它的工作,而不是关注授权。将此留给决定是否调用该方法的部分。