[Asp.net MVC]Asp.net MVC5系列——在模型中添加验证规则
上篇文章中介绍了添加数据,在提交表单的数据的时候,我们需要对数据的合法性进行校验,Asp.net MVC5中,提供一种方便的验证方式。本文介绍如何在我们的Student模型中添加一些验证规则,同时确认当用户使用我们的应用程序创建或编辑学生信息时将使用这些验证规则对用户输入的信息进行检查。
DRY原则
在ASP.NET MVC中,有一条作为核心的原则,就是DRY(“Don’t Repeat Yourself,中文意思为:不要让开发者重复做同样的事情)原则。ASP.NET MVC提倡让开发者“一处定义、处处可用”。这样可以减少开发者的代码编写量,同时也更加便于代码的维护。
在模型中添加验证规则
首先,让我们在Student类中追加一些验证规则。
打开Student.cs文件,在文件的头部追加一条引用System.ComponentModel.DataAnnotations命名空间的using语句,代码如下所示。
1 using System.ComponentModel.DataAnnotations;
这个System.ComponentModel.DataAnnotations命名空间是.NET Framework中的一个命名空间。它提供了很多内建的验证规则,你可以对任何类或属性显式指定这些验证规则。
现在让我们来修改Student类,增加一些内建的Required(必须输入),StringLength(输入字符长度)与Range(输入范围)验证规则,当然,我们也可以自定义我们自己的验证规则,之后会说明如何创建自定义验证规则。
复制代码
1 //------------------------------------------------------------------------------
2 // <auto-generated>
3 // 此代码已从模板生成。
4 //
5 // 手动更改此文件可能导致应用程序出现意外的行为。
6 // 如果重新生成代码,将覆盖对此文件的手动更改。
7 // </auto-generated>
8 //------------------------------------------------------------------------------
9
10 namespace Wolfy.FirstMVCProject.Models
11 {
12 using System;
13 using System.Collections.Generic;
14 using System.ComponentModel.DataAnnotations;
15
16 public partial class Student
17 {
18 public Student()
19 {
20 this.Score = new HashSet<Score>();
21 }
22
23 public int stuId { get; set; }
24 [Required(ErrorMessage = "必须输入标题")]
25 public string stuName { get; set; }
26
27 public string stuSex { get; set; }
28 public System.DateTime stuBirthdate { get; set; }
29 public System.DateTime stuStudydate { get; set; }
30 [StringLength(4, ErrorMessage = "只能输入4个字符")]
31 public string stuAddress { get; set; }
32 [Required(ErrorMessage = "必须输入标题")]
33 //正则验证
34 [RegularExpression(@"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$", ErrorMessage = "邮箱格式不正确")]
35 public string stuEmail { get; set; }
36 [RegularExpression(@"\d{11}", ErrorMessage = "邮箱格式不正确")]
37 public string stuPhone { get; set; }
38 public Nullable<bool> stuIsDel { get; set; }
39 public Nullable<System.DateTime> stuInputtime { get; set; }
40 public int classId { get; set; }
41
42 public virtual Course Course { get; set; }
43 public virtual ICollection<Score> Score { get; set; }
44 }
45 }
复制代码
上述这些验证属性指定了我们想要强加给模型中各属性的验证规则。Required属性表示必须要指定一个属性值,在上例中,一个有效的学生信息必须含有标题,地址,电话,邮箱。Range属性表示属性值必须在一段范围之间。StringLength属性表示一个字符串属性的最大长度或最短长度。
Action中的代码
复制代码
1 [HttpPost]
2 public ActionResult Create(Student student)
3 {
4 //ModelState.IsValid校验客户端数据是否全部符合验证规则
5 if (ModelState.IsValid)
6 {
7 //获取dropdownlist选中的value值
8 string strClassID = Request.Form["class"];
9 int intId = Convert.ToInt32(strClassID);
10 var course = from c in entity.Course
11 where c.classId == intId
12 select c;
13 //处理外键关系
14 student.Course = course.FirstOrDefault();
15 entity.Student.Add(student);
16 entity.SaveChanges();
17 return RedirectToAction("Index");
18
19 }
20 else
21 {
22 //在不符合验证规则的时候,得重新绑定DropDownList数据源。
23 var courses = from s in entity.Course
24 select s;
25 List<SelectListItem> items = new List<SelectListItem>();
26 foreach (var item in courses)
27 {
28 SelectListItem selectListItem = new SelectListItem() { Text = item.className, Value = item.classId.ToString() };
29 items.Add(selectListItem);
30 }
31 ViewData["class"] = items;
32 return View(student);
33 }
34 }
复制代码
运行效果
自定义验证规则
如果上面的验证规则,不能满足需要,可以自己定义验证规则,首先看一下,Required是如何实现的,咱们就模仿Required来实现一个自己的验证规则。
复制代码
1 namespace System.ComponentModel.DataAnnotations
2 {
3 // 摘要:
4 // 指定需要数据字段值。
5 [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
6 public class RequiredAttribute : ValidationAttribute
7 {
8 // 摘要:
9 // 初始化 System.ComponentModel.DataAnnotations.RequiredAttribute 类的新实例。
10 public RequiredAttribute();
11
12 // 摘要:
13 // 获取或设置一个值,该值指示是否允许空字符串。
14 //
15 // 返回结果:
16 // 如果允许空字符串,则为 true;否则为 false。 默认值为 false。
17 public bool AllowEmptyStrings { get; set; }
18
19 // 摘要:
20 // 检查必填数据字段的值是否不为空。
21 //
22 // 参数:
23 // value:
24 // 要验证的数据字段值。
25 //
26 // 返回结果:
27 // 如果验证成功,则为 true;否则为 false。
28 //
29 // 异常:
30 // System.ComponentModel.DataAnnotations.ValidationException:
31 // 数据字段值为 null。
32 public override bool IsValid(object value);
33 }
34 }
复制代码
复制代码
1 // 摘要:
2 // 作为所有验证属性的基类。
3 //
4 // 异常:
5 // System.ComponentModel.DataAnnotations.ValidationException:
6 // 在设置非本地化 System.ComponentModel.DataAnnotations.ValidationAttribute.ErrorMessage
7 // 属性错误消息的同时,本地化错误消息的 System.ComponentModel.DataAnnotations.ValidationAttribute.ErrorMessageResourceType
8 // 和 System.ComponentModel.DataAnnotations.ValidationAttribute.ErrorMessageResourceName
9 // 属性也被设置。
10 public abstract class ValidationAttribute : Attribute
11 {
12 //其他代码
13 }
复制代码
所以,验证规则特性必须集成ValidationAttribute类,当然也可以继承该类的子类。(注意:对于特性约定以Attribute结尾)。
我们就自定义一个验证类,实现默认值约束规则DefaultsAttribute,而实现最简单的方式就是自定义正则表达式的规则。
定义的验证类的代码如下:
复制代码
1 public class DefaultsAttribute : RegularExpressionAttribute
2 {
3 public DefaultsAttribute()
4 : base("[mf]")
5 {
6
7 }
8 public override string FormatErrorMessage(string name)
9 {
10 return "性别只能输入m(男)或者f(女)";
11 }
12 }
复制代码
为Student类中的stuSex加上特性。
1 [Defaults]
2 public string stuSex { get; set; }
然后测试一下,看看实现效果
在Create视图(追加学生信息视图)与Create方法内部是如何实现验证的?
该方法中的ModelState.IsValid属性用来判断是否提交的学生信息数据中包含有任何没有通过数据验证的无效数据。如果存在无效数据,Create方法重新返回追加学生信息视图。如果数据全部有效,则将该条数据保存到数据库中。
我们之前创建的使用支架模板的Create.cshtml视图模板中的代码显示如下,在首次打开追加学生信息视图与数据没有通过验证时,Create方法中返回的视图都是使用的这个视图模板。
复制代码
1 @model Wolfy.FirstMVCProject.Models.Student
2
3 @{
4 Layout = null;
5 }
6
7 <!DOCTYPE html>
8
9 <html>
10 <head>
11 <meta name="viewport" content="width=device-width" />
12 <title>Create</title>
13 </head>
14 <body>
15 @using (Html.BeginForm("Create","Student",FormMethod.Post))
16 {
17 @Html.AntiForgeryToken()
18
19 <p class="form-horizontal">
20 <h4>Student</h4>
21 <hr />
22 @Html.ValidationSummary(true)
23
24 <p class="form-group">
25 @Html.LabelFor(model => model.stuName, new { @class = "control-label col-md-2" })
26 <p class="col-md-10">
27 @Html.EditorFor(model => model.stuName)
28 @Html.ValidationMessageFor(model => model.stuName)
29 </p>
30 </p>
31
32 <p class="form-group">
33 @Html.LabelFor(model => model.stuSex, new { @class = "control-label col-md-2" })
34 <p class="col-md-10">
35 @Html.EditorFor(model => model.stuSex)
36 @Html.ValidationMessageFor(model => model.stuSex)
37 </p>
38 </p>
39
40 <p class="form-group">
41 @Html.LabelFor(model => model.stuBirthdate, new { @class = "control-label col-md-2" })
42 <p class="col-md-10">
43 @Html.EditorFor(model => model.stuBirthdate)
44 @Html.ValidationMessageFor(model => model.stuBirthdate)
45 </p>
46 </p>
47
48 <p class="form-group">
49 @Html.LabelFor(model => model.stuStudydate, new { @class = "control-label col-md-2" })
50 <p class="col-md-10">
51 @Html.EditorFor(model => model.stuStudydate)
52 @Html.ValidationMessageFor(model => model.stuStudydate)
53 </p>
54 </p>
55
56 <p class="form-group">
57 @Html.LabelFor(model => model.stuAddress, new { @class = "control-label col-md-2" })
58 <p class="col-md-10">
59 @Html.EditorFor(model => model.stuAddress)
60 @Html.ValidationMessageFor(model => model.stuAddress)
61 </p>
62 </p>
63
64 <p class="form-group">
65 @Html.LabelFor(model => model.stuEmail, new { @class = "control-label col-md-2" })
66 <p class="col-md-10">
67 @Html.EditorFor(model => model.stuEmail)
68 @Html.ValidationMessageFor(model => model.stuEmail)
69 </p>
70 </p>
71
72 <p class="form-group">
73 @Html.LabelFor(model => model.stuPhone, new { @class = "control-label col-md-2" })
74 <p class="col-md-10">
75 @Html.EditorFor(model => model.stuPhone)
76 @Html.ValidationMessageFor(model => model.stuPhone)
77 </p>
78 </p>
79
80 <p class="form-group">
81 @Html.LabelFor(model => model.stuIsDel, new { @class = "control-label col-md-2" })
82 <p class="col-md-10">
83 @Html.EditorFor(model => model.stuIsDel)
84 @Html.ValidationMessageFor(model => model.stuIsDel)
85 </p>
86 </p>
87
88 <p class="form-group">
89 @Html.LabelFor(model => model.stuInputtime, new { @class = "control-label col-md-2" })
90 <p class="col-md-10">
91 @Html.EditorFor(model => model.stuInputtime)
92 @Html.ValidationMessageFor(model => model.stuInputtime)
93 </p>
94 </p>
95
96 <p class="form-group">
97 @Html.LabelFor(model => model.Course.classId, "stuClass", new { @class = "control-label col-md-2" })
98 <p class="col-md-10">
99 @Html.DropDownList("class", String.Empty)
100 @Html.ValidationMessageFor(model => model.classId)
101 </p>
102 </p>
103
104 <p class="form-group">
105 <p class="col-md-offset-2 col-md-10">
106 <input type="submit" value="Create" class="btn btn-default" />
107 </p>
108 </p>
109 </p>
110 }
111
112 <p>
113 @Html.ActionLink("Back to List", "Index")
114 </p>
115 </body>
116 </html>
复制代码
请注意在这段代码中使用了许多Html.EditorFor帮助器来为Student类的每个属性输出一个输入文本框。在每个Html.EditorFor帮助器之后紧跟着一个Html.ValidationMessageFor帮助器。这两个帮助器将与从控制器传入的模型类的对象实例(在本示例中为Student对象的一个实例)结合起来,自动寻找指定给模型的各个验证属性,然后显示对应的验证错误信息。
这种验证*的好处是在于控制器和Create视图(追加学生信息视图)事先都即不知道实际指定的验证规则,也不知道将会显示什么验证错误信息。验证规则和错误信息只在Student类中被指定。
上一篇: 这4G有啥好的
下一篇: 先降价再变色:黑莓依然坚挺