在ASP.NET MVC应用程序中,控制器通常负责处理输入和应用程序用户界面(视图)。不希望将业务逻辑嵌入到控制器中。最佳做法是创建一个服务层,它基本上是控制器和数据层之间的一层。当涉及到验证时,例如,想确保单价大于零,或者产品名称从不为空,不想在控制器或视图中编写代码。为此,想将逻辑放入业务层,即模型层。将验证放入模型层的好处是,任何访问数据库的应用程序都将强制执行验证规则。这也意味着可以在一个地方更改验证规则,应用程序中的每个UI元素都将自动更新到数据管理器。对于添加、编辑、删除场景,如果能够在模型层添加验证,所有这些不同的操作规则都会在更新数据库之前强制执行验证规则。
在ASP.NET MVC中,有多种方法可以进行模型级验证。可以在业务层中编写自己的验证逻辑。在ASP.NET MVC版本1中,支持IDataErrorInfo,这是WPF和Windows Forms支持的标准接口。在ASP.NET MVC 2中,有另一个内置机制,它使用数据注解功能,动态数据在ASP.NET Web表单中使用。Silverlight也在使用RIA服务中的这种功能。
以下代码使用IDataErrorInfo接口生成验证错误消息。创建一个扩展由Entity Framework生成的部分Question类的Question类。接下来,向Question类的OnTitleChanging()部分方法添加验证逻辑。最后,实现IDataErrorInfo接口,以便将这些验证消息暴露给ASP.NET MVC框架。
C# using System.Collections.Generic; using System.ComponentModel; namespace MvcApplication1.Models { public partial class Question : IDataErrorInfo { private Dictionary _errors = new Dictionary(); partial void OnTitleChanging(string value) { if (value.Trim().Length > 20) _errors.Add("Title", "Title should not be more than 20 characters."); } #region IDataErrorInfo Members public string Error { get { return string.Empty; } } public string this[string columnName] { get { if (_errors.ContainsKey(columnName)) return _errors[columnName]; return string.Empty; } } #endregion } }
ASP.NET MVC框架使用模型绑定器(DefaultModelBinder)创建传递给Create()操作的Question实例。模型绑定器负责通过将HTML表单字段绑定到Movie对象的实例来创建Question对象的实例。DefaultModelBinder检测类是否实现了IDataErrorInfo接口。如果类实现了这个接口,那么模型绑定器就会为类的每个属性调用IDataErrorInfo.this索引器。如果索引器返回错误消息,那么模型绑定器会自动将此错误消息添加到模型状态。
使用数据注解验证器的优势在于,它们允许通过向类属性添加一个或多个属性(如Required或StringLength属性)来简单地执行验证。
C# using System.ComponentModel; using System.ComponentModel.DataAnnotations; namespace MvcApplication1.Models { [MetadataType(typeof(Question_Validate))] public partial class Question { } public class Question_Validate { [StringLength(20, ErrorMessage = "Title should not be more than 20 characters.")] public object Title { get; set; } } }
注意,Question部分类用MetadataType属性装饰,该属性指向Question_Validate类。Question_Validate类包含Question类的代理属性。
默认情况下,上述示例将在服务器上工作,但要使其与客户端验证一起工作,只需要两个步骤。第一步是引用适当的脚本。
XML <script src="../../Scripts/jquery-1.3.2.min.js" type="text/javascript" /> <script src="../../Scripts/jquery.validate.min.js" type="text/javascript" /> <script src="../../Scripts/MicrosoftAjax.js" type="text/javascript" /> <script src="../../Scripts/MicrosoftMvcValidation.js" type="text/javascript" />
XML <% Html.EnableClientValidation(); %>