- 浏览: 178865 次
- 性别:
文章分类
最新评论
Asp.Net MVC4 系列--进阶篇之Model(2)
在上一章介绍了MVC中model binding,本章将介绍一下MVCmodel validation
和前几章一样,从一个例子开始
准备工作
准备model
public classAppointment { public string ClientName { get; set; } [DataType(DataType.Date)] public DateTime Date { get; set; } public bool TermsAccepted { get; set; } }
代码说明:一个预约model,包含了客户姓名,预约日期,以及是否accept合约
准备controller
public class AppintmentController : Controller { public ViewResult MakeBooking() { return View("NewAppintment",new Appointment { Date = DateTime.Now }); } [HttpPost] public ViewResult MakeBooking(Appointment appt) { //statements to store new Appointment in a //repository would go here in a real project return View("Completed", appt); } }
代码说明:很经典的”Get-Post-action” 结构,同名方法两个,Get版本用于服务第一次来到页面的请求,post版本用于处理提交页面的请求。
Get版本:render预约页面,获取预约信息
Post版本:获得预约的信息,透传(为了演示)给CompletedView表示预约成功
准备View
a.(NewAppintment.cshtml)
@model MVCModelValidation.Models.Appointment @{ ViewBag.Title = "Make A Booking"; } <h4>Book an Appointment</h4> @using (Html.BeginForm()) { <p>Your name: @Html.EditorFor(m =>m.ClientName)</p> <p>Appointment Date:@Html.EditorFor(m => m.Date)</p> <p>@Html.EditorFor(m =>m.TermsAccepted) I accept the terms & conditions</p> <input type="submit" value="Make Booking" /> }
代码说明:预约View
b.Completed
@model MVCModelValidation.Models.Appointment @{ ViewBag.Title = "Completed"; } <h4>Your appointment is confirmed</h4> <p>Your name is:<b>@Html.DisplayFor(m => m.ClientName)</b></p> <p>The date of your appointment is:<b>@Html.DisplayFor(m => m.Date)</b></p>
代码说明:预约成功 View
运行
Make booking
可以看到,代码有几个需要验证的地方:
1.客户姓名必填
2.预约日期必填
3.必须accept 合约
显式验证
由于我们的验证是针对用户提交表单的scenario,因此修改post版本的action就好了:
带validation的action:
[HttpPost] public ViewResult MakeBooking(Appointment appt) { if(string.IsNullOrEmpty(appt.ClientName)) { ModelState.AddModelError("ClientName", "Please enter yourname"); } if(ModelState.IsValidField("Date") && DateTime.Now >appt.Date) { ModelState.AddModelError("Date", "Please enter a date inthe future"); } if (!appt.TermsAccepted) { ModelState.AddModelError("TermsAccepted", "You mustaccept the terms"); } if (ModelState.IsValid) { // statements to store newAppointment in a // repository would go here ina real project return View("Completed", appt); } // statements to store newAppointment in a // repository would go here in areal project return View("NewAppintment", appt); }
代码说明:由于到达这一步我们model已经被完成binding了(具体参见上一章asp.netMVC4系列—进阶篇之Model(1)),因此我们拿出值添加我们的验证逻辑,把相应错误信息放在ModelError里面让MVCFramework拿走,最后判断Model.IsValid,如果没有任何错误,这个属性为True。那么这些信息如何在View中显示出来呢?
修改NewAppointment.cshtml
@model MVCModelValidation.Models.Appointment @{ ViewBag.Title = "Make ABooking"; } <h4>Book an Appointment</h4> @using (Html.BeginForm()) { @Html.ValidationSummary() <p>Your name:@Html.EditorFor(m => m.ClientName)</p> <p>Appointment Date:@Html.EditorFor(m => m.Date)</p> <p>@Html.EditorFor(m =>m.TermsAccepted) I accept the terms & conditions</p> <input type="submit" value="Make Booking" /> }
我们只添加了一行:
@Html.ValidationSummary()
这样,就可以display我们action中添加的错误信息了。
运行
不填名字也不勾选terms& conditions,make booking
可以看到,我们手动的验证逻辑工作了,并且错误信息也显示了。
如果需要改显示出来的错误信息的css,可以修改:
~/Content/Site.css中的.validation-summary-errors
Html.ValidationSummary的其他重载
Html.ValidationSummary(bool) |
是否只显示model级别的error(后面会演示) |
Html.ValidationSummary(string) |
在所有错误信息显示前,显示一条总的错误信息 |
Html.ValidationSummary(bool,string) |
前两种情况的组合 |
Model 级别的错误
依旧修改刚才post版本的MakeBookingAction
添加一个验证逻辑:
if (ModelState.IsValidField("ClientName") &&ModelState.IsValidField("Date") && appt.Date.DayOfWeek ==DayOfWeek.Monday) { ModelState.AddModelError("", "Sorry , Can notappointments on Mondays"); }
在View中使用另一个Html.ValidationSummary的重载(只显示model error):
@Html.ValidationSummary(true)
填所有信息(日期选一个monday),尝试makebooking
可以看到,modellevel的验证生效,并且只显示了modellevel的错误信息。
显示Property级别的信息
修改NewAppointment.cshtml(Form部分):
@using (Html.BeginForm()) { @Html.ValidationSummary(true) <p>@Html.ValidationMessageFor(m=> m.ClientName)</p> <p>Your name:@Html.EditorFor(m => m.ClientName)</p> <p>@Html.ValidationMessageFor(m=> m.Date)</p> <p>Appointment Date:@Html.EditorFor(m => m.Date)</p> <p>@Html.ValidationMessageFor(m=> m.TermsAccepted)</p> <p>@Html.EditorFor(m =>m.TermsAccepted) I accept the terms & conditions</p> <input type="submit" value="MakeBooking" /> }
我们对每个需要显示错误信息的字段添加了Html.ValidationMessageFor,这样就可以了。
运行
为了验证View的逻辑,把所有信息清空
Make booking
可以看到我们为每个字段添加的ValidationForMessage方法生效了,并显示了property级别的错误信息
把验证放在metadata完成
MVC Framework把验证作为了一个concern,也就是AOP的思想。MVCFramework 给我们提供了足够的Validation的Attribute让我们使用,我们可以在model里面根据需要添加不同的Attribute就可以完成我们的验证,避免在Controller中出现类似的重复的验证逻辑,而controller只需要专注自己的职责(操作domainmodel,选择View)
重构代码
1.Model
public class Appointment { [Required(ErrorMessage = "Please provide a name")] public string ClientName { get; set; } [Required(ErrorMessage = "Please enter a date")] [DataType(DataType.Date)] public DateTime Date { get; set; } [Range(typeof(bool), "true", "true", ErrorMessage ="You must accept the terms")] public bool TermsAccepted { get; set; } }
2.把Controller的验证逻辑拿掉
[HttpPost] public ViewResult MakeBooking(Appointment appt) { if (ModelState.IsValid) { // statements to store newAppointment in a // repository would go here ina real project return View("Completed", appt); } // statements to store new Appointment in a // repository would go here in a real project return View("NewAppintment", appt); }
3.View不用改
4.运行
可以看到,重构后(meta data版本)的代码工作了。
Validation Attribute
Compare |
传入类型,指定一个值和要对比的值 |
Range |
传入一个范围 |
RegularExpression |
指定正则表达式 |
Required |
非空 |
StringLength |
限制字符串长度 |
Customize Attribute
1.继承Validation Attribute
public class MustBeTrueAttribute : ValidationAttribute { public override bool IsValid(object value) { return value is bool && (bool)value; } }
2.使用
public class Appointment { [Required(ErrorMessage ="Please provide a name")] public string ClientName {get; set; } [Required(ErrorMessage ="Please enter a date")] [DataType(DataType.Date)] public DateTime Date { get;set; } [MustBeTrue(ErrorMessage ="You must accept the terms")] public bool TermsAccepted {get; set; } }
3.运行
Make booking
继承built-in的attribute
1.实现
public class FutureDateAttribute : RequiredAttribute { public override bool IsValid(object value) { return base.IsValid(value) && ((DateTime)value) > DateTime.Now; } }
2.使用
public class Appointment { [Required(ErrorMessage = "Please provide a name")] public string ClientName { get; set; } [FutureDate(ErrorMessage = "Please Enter a Future Date")] [DataType(DataType.Date)] public DateTime Date { get; set; } [MustBeTrue(ErrorMessage = "You must accept the terms")] public bool TermsAccepted { get; set; } }
3.运行
Make booking
可以看到futuredate 验证生效,更新一下日期提交
可以看到预约成功。
Model level 验证
1.实现
public class NoMondayBookingAttribute : ValidationAttribute { public NoMondayBookingAttribute() { ErrorMessage ="Can not book appointments on Mondays temporary"; } public override bool IsValid(object value) { var app = value asAppointment; if (app == null ) { // we don't have amodel of the right type to validate, or we don't have // the values forthe ClientName and Date properties we require return true; } return app.Date.DayOfWeek != DayOfWeek.Monday; } }
代码说明:验证是否为appointment类型,如果是,取出日期,如果为周一返回false,其他情况返回true
2.使用
[NoMondayBooking] public class Appointment { [Required(ErrorMessage ="Please provide a name")] public string ClientName {get; set; } [FutureDate(ErrorMessage ="Please Enter a Future Date")] [DataType(DataType.Date)] public DateTime Date { get;set; } [MustBeTrue(ErrorMessage ="You must accept the terms")] public bool TermsAccepted {get; set; } }
3.运行
输入所有信息,日期选择下周一,符合所有property验证的要求
Make booking
可以看到,由于预约为下周一,因此modellevel的验证没过,而我们View的实现没改,我们现在是ValidateSummary(true),只显示model level的错误信息。
我们改到下周二重新提交
可以看到预约成功,通过了model level验证。
IValidatableObject
如果希望把validation的职责加在model上,可以实现IValidatableObject接口,下一版model代码:
public class Appointment : IValidatableObject { public string ClientName {get; set; } [DataType(DataType.Date)] public DateTime Date { get;set; } public bool TermsAccepted {get; set; } public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) { var errors = new List<ValidationResult>(); if(string.IsNullOrEmpty(ClientName)) { errors.Add(new ValidationResult("Please enter your name")); } if (DateTime.Now >Date) { errors.Add(new ValidationResult("Please enter a date in the future")); } if (errors.Count == 0&& Date.DayOfWeek == DayOfWeek.Monday) { errors.Add( new ValidationResult("cannot book appointments on Mondays")); } if (!TermsAccepted) { errors.Add(new ValidationResult("You must accept the terms")); } return errors; } }
这样就实现了和前面示例验证逻辑一模一样的验证,可以仍推荐使用AOP的思路(Attribute)进行validate。
客户端验证
MVC framework提供unobstrusive javascript使得我们可以方便的进行客户端验证
1.Appsetting添加
<appSettings> <add key="ClientValidationEnabled"value="true"/> <add key="UnobtrusiveJavaScriptEnabled" value="true"/> </appSettings>
2.需要的js:
/Scripts/ jquery-1.7.1.min.js /Scripts/ jquery.validate.min.js /Scripts/ jquery.validate.unobtrusive.min.js
通常,创建basic的mvc sln默认的jsbundle已添加(BundleConfig.cs):
bundles.Add(newScriptBundle("~/bundles/jqueryval").Include( "~/Scripts/jquery.unobtrusive*", "~/Scripts/jquery.validate*"));
在View中Render:
@Scripts.Render("~/bundles/jqueryval")
分析开启客户端验证后生成了一个htmlinput
<input class="text-box single-line" data-val="true" data-val-length="The field ClientName must be a string with aminimum length of 3 and a maximum length of 10." data-val-length-max="10" data-val-length-min="3" data-val-required="The ClientName field is required."id="ClientName" name="ClientName" type="text" value=""/>
MVC Framework会找到data-val属性,如果为true说明需要客户端验证,然后解析data-val开头的验证类型,例如data-val-length,data-val-length-min,
data-val-length-max . data-val-required 等等。
MVC framework的客户端验证部分,是基于jquery的。
相关推荐
ASP.NET MVC 5 - 开始MVC 5之旅 2. ASP.NET MVC 5 - 控制器 3. ASP.NET MVC 5 - 视图 4. ASP.NET MVC 5 - 将数据从控制器传递给视图 5. ASP.NET MVC 5 - 添加一个模型 6. ASP.NET MVC 5 - 创建连接字符串并使用SQL ...
ASP.NET MVC学习笔记-Controller与View传值.
ASP.NET MVC 身份验证-利用cookie记录登录用户
asp.net MVC4 CMS 完整的源代码,学习和提高asp.net mvc4可以参考一下。
本系列共11篇文章,翻译自ASP.NET MVC 5 官方教程,由于本系列文章言简意赅,篇幅适中,从一个web网站示例开始讲解,全文最终完成了一个管理影片的小系统,非常适合新手入门ASP.NET MVC 5 (新增、删除、查询、更新) ...
ASP.NET MVC 1.0 MSDN Reference CHM Version ASP.NET MVC 1.0 MSDN 参考及类库,CHM版本,从MSDN 官方网站下载并编译。源分支URL: http://msdn.microsoft.com/en-us/library/dd394709.aspx 内容列表: ASP.NET MVC...
ASP.NET MVC3.0实例-Movies
asp.net mvc demo 2015-08-25
MVC专家“梦之队”对ASP.NET MVC 4的全新诠释 由Microsoft专家和极受敬重的软件开发社区负责人撰写的《ASP.NET MVC 4高级编程(第4版)》将带您学习最前沿的Web框架:ASP.NET MVC 4。本书开篇简要介绍ASP.NET MVC框架...
ASP.NET MVC 4 in Action is a hands-on guide that shows you how to apply ASP.NET MVC effectively. After a high-speed ramp up, this thoroughly revised new edition explores each key topic with a self-...
ASP.NET MVC 是微软官方提出的一种Web开发框架,通过M是模型(model)-V视图(view)-C控制器(controller)l来设计创建Web应用程序。截至目前最新版本是MVC5,相对于之前的版本MVC5其可扩展性、易用性等方面都不很大的...
Adam Freeman-Pro ASP.NET Core MVC 2-Apress (2017) 一如既往的好书!
asp.net mvc4
MVC架构模式是近年来编程世界里最长被提及的模式之一,Model View Controller(模型-视图-控制器,MVC)模式将你的软件组织并分解成三个截然不同的角色: ◆Model封装了你的应用数据、应用流程和业务逻辑。 ◆View从...
Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程 Asp.Net MVC案例教程
全网首发:ASP.NET MVC4 开发指南(附带源码)版本,ASP.NET MVC4 开发指南 PDF + ASP.NET MVC4 开发指南源码,让你学习起来再也不费劲,轻松高效!
本书共分为12章,以符合初学者思维的方式系统地介绍ASP.NET MVC的应用技巧,并结合实际项目详细地介绍如何基于ASP.NET MVC构建企业项目。通过本书的学习,读者可以全面掌握ASP.NET MVC的开发,并从代码中获取软件...
ASP.NET MVC4,全英文的教程,大家英语好的可以原汁原味的看看
ASP.NET MVC in Action is a comprehensive guide to MVC-based development using this powerful framework. It offers a clearly-written introduction both to the ASP.NET MVC Framework and to the MVC ...