用EF Code First和ASP.Net MVC3进行类级别模型验证
你能应用验证属性attribute)—— 如.NET 4内置的[Required],[Range]—— [RegularExpression] 到你的模型类中,从而保证存储到数据库之前模型属性的有效性得到验证。你也能生成你自己的定制验证属性像这个比较酷的[CreditCard]validator)并将他们通过EF Code First自动强制实施。这是一个在你的模型中验证属性值的简单方法。我在我之前的博客展示了这种操作的一些示例代码。
使用IValidatableObject实施类级别模型验证
数据注释属性供了一种简单的方法来验证你的模型类中的单个属性值。
有些人问道:是否EF Code First也支持在模型对象上应用类级别验证方法,只管验证规则而不需要涉及很多属性值? 答案是肯定的——你有一个很简单的方法来实现:在你的模型类中实现IValidatableObject接口。
IValidatableObject.Validate()方法
下面是一个在Product模型类中使用IvalidatableObject接口(包含于.NET4的System.ComponentModel.DataAnnotaions命名空间内)实现两个定制验证规则的示例。这两个规则保证:
· 如果产品(product)处于断货状态,新单品(Unit)不能被订购
· 如果库存超过100 Unit,新单品(Unit)不能被订购
我们将通过实现我们的Product 类中的IValidatableObject接口和它的Validate()方法来强制实施这些商业规则,像这样:
IValidatableObject.Validate()方法能应用涉及多个属性的验证规则,并返回多方个验证错误。每个返回的验证结果都提供一个错误消息和一个导致验证冲突的候选属性名称列表(这对显示UI内的错误信息非常有用)。
强制自动验证
在实现了IvalidatableObject接口的模型对象被保存的时候,EF Code First(自CTP5起)现在会自动调用Validate()方法。你无需写任何代码来实现它——现在这个是默认支持的。
这个新支持意味着下面违反了上面所说的一条商业规则的代码将在我们调用Northwind.DBContext的“SaveChanges()“方法的时候自动抛出一个异常(并中止事务)。
除了相应地处理验证异常之外,EF Code First还允许你主动检查验证错误。自CTP5开始, 你能调用DbContext基类的GetValidationErrors()方法来返回一列被处理模型对象中的验证错误。GetValidationErrors()将返回所有验证错误——不管他们是通过数据批注属性(DataAnnotation Attribute)还是通过IValidatableObjectValidate()实现生成的。
以下是一个在尝试调用SaveChanges()前使用
GetValidationErrors()方法主动检查错误的示例:
ASP.Net MVC3和IValidatableObject
对与ASP.NET MVC的模型绑定结构一起使用的模型对象,ASP.NET MVC2支持其数据批注属性的自动强制实施。 ASP.Net MVC3走的更远,它还支持IValidatableObject接口。在有验证错误的时候,这个对模型验证的综合支持使显示窗体内的错误信息变得简单。
为了演示这个操作,让我们研究一个简单的允许用户生成新product的Create窗口:
我们能使用一个包含下面2个方法的ProductController类来实现上面的两个Create功能:
第一个Create()方法实现一种/Product/Create URL来处理HTTP-GET请求,并显示HTML表单以供填写。第二个Create()方法实现另一种/Product/Create URL来处理HTTP-Post请求——它取出提交的表单数据,保证它的有效性,如果有效的话将其保存在数据库内。 如果验证有问题,它会重新显示表单和它提交的值。
我们的“Create”视图(描述表单的)的Razor视图模板类似下面这样:
在上面的控制器视图实现中亮点之一是我们没有写任何验证逻辑在里面。验证逻辑和商业规则完全在我们的模型层实现,而ProductsController只通过简单地检查它是否有效——通过调用ModelStateIsValid Helper 方法 ——来决定是去试着保存改动还是重新显示带有错误的窗体。我们的视图调用的
Html.ValidationMessageFor()Helper方法只简单地显示我们的Product模板的数据批注和IValidatableObject.Validate()方法所返回的错误信息。
我们能通过在表单中输入非法数据并尝试提交重现以上场景。
注意上面当我们点“Create“按钮的时候我们是怎样得到一个错误信息的。这是因为我们选中了”Discontinued“复选框的同时输入了一个UnitsOnOrder值(所以违反了我们的商业规则中的一条)。
你可能会问:ASP.Net MVC如何知道要在UnitsOnOrder文本框旁高亮显示错误信息的?这是因为ASP.NET MVC 3在实现模型绑定的时候支持IvalidatableObject接口,它会返回其验证失败的错误信息。
我们的产品模型类中的商业规则指定我们的商业规则被违反的时候”UnitsOnOrder”属性必须被高亮显示。
因为上面的属性名提示,所以我们的Html.ValidationMessageFor()helper方法知道要在UnitsOnOrder编辑框旁边显示商业规则错误信息:
保持代码“干燥”(DRY:Don’t repeat yourself)
ASP.NET MVC和EF Code First使你能将验证和商业规则置于同一个地方(在你的模型层中),防止它们溜到你的控制器和视图里去。
在模型层放置验证逻辑可以帮助防止你在往应用程序中添加更多的控制器和视图的时候重复验证/商业逻辑。它允许你在一个地方(你的模型层中)快速更改你的商业规则/验证逻辑,并立刻在你应用程序中所有的控制器/视图中体现出来。这让你的程序代码干净,容易维护,并能在将来很容易演化和升级。