所有经过 URL 路由过滤过的请求都将会映射到一个特定的控制器上,并由这个控制器上指定的方法来执行处理。因此,控制器就是开发者写代码来处理请求的地方。现在,让我们简要浏览一下控制器的方方面面。
控制器粒度
一个 ASP.NET MVC 应用程序通常由若干控制器类组成。但是,到底我们需要有多少控制器?具体的数量还是由你决定,主要看你怎么组织应用中的行为。事实上,你也可以在你的应用程序中设置一个控制器,并把所有处理请求的行为放在这个控制器中。
一个最常用的实践方式是,为你应用中的每一个重要功能的实现分别创建一个控制器。比如,你可以创建一个 CustomerController 类来处理查询,删除,更新,添加用户的请求。同样的,你也可以创建一个 ProductController 来处理与产品相关的请求,等等。大多数的时候,这些控制器对象都直接与应用主菜单中的项目相关联。
一般的,我们可以认为控制器的粒度就是一个用户界面函数的粒度。
无状态组件
程序会为每一个请求实例化一个新的控制器对象。所有你为控制器添加的可能的状态都与请求的生命周期相绑定。为了能使控制器正常工作,他必须能够从 HTTP 请求流和 HTTP 上下文中获取到相关的数据。
未来分层由你决定
常常, ASP.NET MVC 和控制器类表现的很神奇以致你更想对它分层来让应用显得干净,提高可读性和可维护性。就这一点而言,控制器的无状态特性起了很大的帮助,但是这并不足够。
在 ASP.NET MVC 中,控制器与触发请求的用户界面和创建视图的引擎相分离的。控制器处于视图和后台系统之前。虽然,从视图的角度出发,这样的分离很好,并且解决了 ASP.NET Web Forms 的缺点。但是这并不保证你的代码就达到了关注点分离的原则。
你可以牢记,没有任何东西,即使在 ASP.NET MVC 中,可以阻止你直接在控制器中直接使用 ADO.NET 来调用 T-SQL 语句。控制器不是后台系统,而且也不是业务逻辑层。相反的,它应该被认为是 Web Forms 隐藏代码类的副本。因此,从概念上讲,他应该从属于表示层,而不是业务逻辑层。
高可测试性
控制器与身俱来的无状态特性与它那和视图的完美分离使得控制器类非常容易测试。然而,控制器真正的可测试性还应当评估它的有效分层的程度。
虽然你可以向控制器传入任何你指定的输入,并且它的输出也不会出现大的问题,但是对于行为方法的内部结构就不敢保证了。行为方法的实现与外部资源关联的越深(比如,数据库,服务,组件),那么控制器的可测性就会越难。