原文地址:Validating with a Service Layer
前面两篇相关的帖子:
在ASP.NET MVC Framework 中执行简单验证(翻的)
在ASP.NET MVC Framework中使用IErrorDataInfo接口实现验证(翻的)
本指南主要描述一种在ASP.NET MVC应用程序中执行验证的方法。可以学习到如何把验证逻辑代码从controller中分离出来,并放到service层中去。
关注分离
当创建一个ASP.NET MVC应用程序的时候,不应该把数据库相关的逻辑放在controller中的action里。混合数据库和controller的逻辑会造成应用程序在一段时间后难以维护。推荐做法是把所有有关数据库的逻辑分离出来,放在一个repository层中。
比如说,下图中包含了一个简单的repository:ProductRepository,它包含程序中所有的数据访问代码,代码中定义了一个IProductRepository接口以及对这个接口的实现。
在下面的代码中,controller在Index和Create action中使用了repository,注意这个控制器并没有包含任何的数据库逻辑。
创建一个repository层,能够使你保持一个清晰的“关注分离”。控制器负责应用程序流控制逻辑,而repository负责数据访问逻辑。
创建一个service层
现在我们的应用程序流控制逻辑从控制器开始,数据库访问逻辑由repository负责,现在我们要把验证逻辑放在哪里呢?一个选择就是把验证代码放到“Service”层中。
比如说,下图中的product service层,包含一个CreateProduct()方法,这个方法在把新增的product传递到product repository之前调用ValidateProduct()方法验证新增的product。
下图为修改后的ProductController,使用service层代替repository层,controller层和service层打交道。service层和repository层打交道,层与层的功能是完全分离的。
注意:product service的实例由ProductController构造方法创建,当product service创建好了,模型视图字典也传递给了它。product service使用模型状态(model state)为controller传递验证错误信息。
Sevice层的解耦
我们在隔离controller和service层的时候失败了,controller和service层通过模型状态(model state)通信,换句话说,service层对ASP.NET MVC Framework有一个依赖关系。
我们想把service层从controller层中尽可能的隔离出来,理论上说,我们可以使用这个service层为任何不同类型的应用程序服务,而不仅仅只是ASP.NET MVC 应用程序。比如说当以后我们可能需要做一个WPF的客户端程序的时候,所以我们现在要想办法解除掉service层对ASP.NET MVC模型视图的依赖。
在下图中,service层又一次被修改了,不再使用模型视图,改为它可以使用任何实现IValidationDictionary接口的类型。
下面是IValidationDictionary接口的定义。这个接口非常简单,只有一个方法和一个属性。
在下图中,ModelStateWrapper的类实现了IValidateDictionary接口,你可以通过传递一个模型状态(model state)字典给构造方法来实例化ModelStateWrapper类。
最终修改好的controller在构造方法中service层的时候,使用了ModelStateWrapper。如图:
使用IValidationDictionary接口和ModelStateWrapper类,使我们完全把service层从controller层中隔离出来了。service层不再对模型状态(model state)产生任何依赖。你可以传递任何实现了IValidationDictionary接口的类给service层。比如说一个WPF应用程序中可能也有一个也实现了IValidationDictionary接口的简单的集合类。
总结
这篇指南讨论了如何在ASP.NET MVC应用程序中执行验证的另一种方法。在这篇指南中,你学习了如何把验证逻辑从contoller中分离到出来,放在service层中,同样也学习了如何通过创建一个ModelStateWrapper类,把controller层和service层彻底隔离。