ASP.NET MVC 学习7、为Model Class的字段添加验证属性(validation attribuate)
Adding Validation to the Model ,在Model中添加数据验证
本文内容:
这一节我们在Movie Model中添加逻辑验证(validation logic),从而确保我们在页面中新增和编辑的时候录入的数据是正确的合法的。
ASP.NET MVC一个核心的代码设计原则(code design tenets)是DRY(Don’t Repeat Yourself).ASP.NET鼓励你同样功能的方法或者行为只需要指定一次,然后在项目中所有需要的地方很容易的体现出来。这样减少了你写代码的总量,并且让你的代码更不容易出错,并且更好控制。
ASP.NET MVC和Entity Framework Code First提供的这种验证(validation)就是DRY原则的一个很好的例子。你只需要在一个地方(model class)声明验证规则(validation),这个规则就会在项目中的每一个调用model class的地方(insert,edit)进行验证。
我们现在来看一下,在movie applicaton中添加validation的好处
一、Add Validation Rules to the Movie Model 在Movie Model中添加一些逻辑验证规则
Movie.cs中添加命名空间:using System.ComponentModel.DataAnnotations;
这个命名空间提供了一组内置(build-in)的验证属性,这些验证属性可以声明在Model类中的字段属性前面,对字段属性进行验证。
现在我们用这些内置的Validation Rule [Required],[StringLength],[Range]更新Model Class
//Movie 类实例化的对象相当于Table中的一行,实例的各个属性(ID,Title...)相当于Table中的列
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
//[DataType(DataType.Date)]
[DisplayFormat(DataFormatString="{0:d}")]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1, 100)]
//[DataType(DataType.Currency)]
[DisplayFormat(DataFormatString = "{0:c}")]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
}
Ctrl+F5运行程式:
这是因为我们更新了Movie Class,Code First检查到movie和datebase中不一致,所以抛出了错误,现在我们用Migrations功能来更新database中的table.
更新前database中table的定义:
执行migrations功能更新db:
PM>add-migration AddDataAnnotationsMig
PM>update-database
刷新资料库后我们看到Table的定义和movie class进行了同步:
1,Title不能为空2,Genre不能为空,3,Rating 的长度为5
Migrations完成以后,Migrations文件夹下面添加了新了迁移类文件:
迁移类的Up方法更新了表中的约束,Titel,Genre不能为空,Rating字段的长度为5
这些validation attributes 对model class中字段进行约束。Required代表字段必须有值,Range 代表字段值需要在特定的范围之内,StringLength代表字段值的最大长度,默认情况下是任意长度。其他的一些validations attribute例如:decimal,int,float,DateTime默认不能为空的,所以前面不用再加[Required]
Code First 机制会确保在model class加的validation rules会在网页数据保存到database之前执行。例如,我们在movie class的index方法中添加下面的code在执行到SaveChanges()方法的时候就会抛出错误,因为movie的部分属性丢失,并且价格为0不在(1-100)之间。
{
MovieDBContext db = new MovieDBContext();
Movie movie = new Movie();
movie.Title = "Gone with the Wind";
movie.Price = 0.0M;
db.Movies.Add(movie);
db.SaveChanges(); // <= Will throw server side validation exception
return View(db.Movies.ToList());
}
调试弹出错误:
这种由.NET Framework自动执行的验证机制(validation rules)可以让你的代码更加强健。也会确保你忘记对数据进行验证或者是不小心疏忽把错误的数据录入database.
二、 页面上的验证提示Validation Error UI in ASP.NET MVC
我们添加一个新的movie:
我们填写的数据不符合规则,当鼠标移开文本框的时候,页面就提示我们输入的数据不合法,这样的机制在客户端和服务器端都保证了数据符合规则。这样最大的好处就是,你不用再像ASP.NET那样在后台或者前台添加单独的代码对所有录入的数据一一进行判断是否符合规则。Controller和Views自动就会调用model class 中指定的validations rules来检查数据。
我们再来看一下Title和Genre ,这两个字段,movie class中对这两个字段只添加了[Require]的validation attribute,我们没有输入的时候也没有红色提示说必须输入。但是一旦我们提交按钮,或者输入文字后鼠标焦点移开文本框就会有提示说是必填字段。
当页面中所有的数据都是正确的时候,页面数据才会提交到server端
三、 验证是如何在View中和 Action方法中实现的
我们会想,我们只是在movie class中添加了[Require]之类的validation attribute。并没有在view和action方法中添加验证,那么view和action方法是如果实现对数据的验证的呢?
我们先看一下Action Method中的post请求的create方法。方法中调用了ModelState.IsValid
来验证页面提交过来的movie model是否合法,如果不合法,Create
方法就会再次返回到form里面去,如果数据正确,Create方法就会把新的数据保存到数据库
public ActionResult Create(Movie movie)
{
if (ModelState.IsValid)
{
db.Movies.Add(movie);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
由于我们页面段有JavaScript验证,如果数据不合法页面就直接提示错误,就不会把数据通过POST方法提交的服务器。现在我们禁用页面的JavaScript检查,来看一下Action Method具体是如何对数据进行验证的。
1,禁用浏览器的JavaScript,页面就不会提示数据错误了
2,在ActionResult Create中下断点,调试我们看到,前台页面不会报错:
但是ModelState.IsValid==false
页面直接return view,页面提示数据错误:
我们再来看一下View中时如果对这些数据进行检查的:
Html.EditorFor
相当于HTML中的<input>文本框,代表movie中的属性
Html.ValidationMessageFor
对<input>中的数据进行检查
这两个Html Helper方法从Controller中接收数据,并自动查询Model中的验证属性,并提示错误的信息。
这样的验证机制,View和Controller中根本不知道数据验证规则(validation rule),这个规则只需要写在Model Class中,这些验证就自动套用到其他需要的views template中,例如create template and edit tempalte.
如果你想更改valudation rule ,你只需要在model class中进行更改, view和controller中默认就会执行这个验证。这就是DRY原则
四、 在Movie Model中添加格式验证Adding Formatting to the Movie Model System.ComponentModel.DataAnnotations;
同样提供了一组内置的格式属性,在view template中显示 Model中的数据对应的格式,如时间格式.
DataType Attribute 并不会对数据格式进行验证,他们只是告诉View页面改如何显示数据,例如DataType.Date
attribute显示不带小时的日期类似的DataType Attribute还有:URL,PhoneNumber等. RegularExpression attribuate 被用来对数据的格式进行验证
我们同样可以用一组DataFormatString
来指定数据应该以怎样的格式呈现。
补充:如果我们更新Model中的Validation Attribuate例如,把Rating的字段长度改为8,[StringLength(8)]运行的时候会提示“由於建立了資料庫,支援 'MovieDBContext' 內容的模型已經變更”的错误。我们更新Configuration的AutomaticMigrationsEnabled为True
PM>update-database
Ctrl+Shift+B重建,Ctrl+F5执行.
下一节我们会再详细看一下Detail Template 和 Delete Template
See You …