ASP.NET MVC学习之模型验证篇

一、学习前的一句话


在这里要先感谢那些能够点开我随笔的博友们。慢慢的已经在博客园中度过一年半了,伊始只是将博客园作为自己学习的记录本一样使用,也不敢将自己的随笔发表到博客园首页,生怕自己的技艺不高,反倒成了笑话。但是随着时间的推移,再也按捺不住这种想法,于是就写了一篇随笔发表到博客园首页。让我意想不到的是有许多人都看了,而且也留下了评论。这让我鼓起勇气写了第二、三、四篇。到现在的连载,这里我希望那些从未发表过随笔的人可以尝试去发表,在这里他人不会嘲讽你,而是会给你更好的建议。说了这么多下面我们继续开始学习ASP.NET
MVC吧。

二、准备工作


1、创建一个ASP.NET MVC
4网站(笔者的命名是MvcStudy)

2、在Models下创建一个Register模型类,具体代码如下所示:

 1 namespace MvcStudy.Models
2 {
3 public class Register
4 {
5 public String UserName { get; set; }
6 public String Password { get; set; }
7 public String RptPassword { get; set; }
8 public String Email { get; set; }
9 public DateTime BirthDate { get; set; }
10 public bool IsApprove { get; set; }
11 }
12 }

3、创建一个名为Home的控制器,并在其中写入下面的代码:

 1 namespace MvcStudy.Controllers
2 {
3 public class HomeController : Controller
4 {
5 public ActionResult Index()
6 {
7 return View();
8 }
9
10 [HttpPost]
11 public ActionResult Index(Register reg)
12 {
13 return View();
14 }
15 }
16 }

4、接着在Views下创建一个Home文件夹并在其中新建一个Index视图,代码如下:

 1 @model MvcStudy.Models.Register
2 @{
3 ViewBag.Title = "Index";
4 }
5
6
7 @using (Html.BeginForm())
8 {
9 <div>
10 用户名:
11 @Html.EditorFor(m => m.UserName)
12 </div>
13 <div>
14 密码:
15 @Html.EditorFor(m => m.Password)
16 </div>
17 <div>
18 重复密码:
19 @Html.EditorFor(m => m.RptPassword)
20 </div>
21 <div>
22 出生日期:
23 @Html.EditorFor(m => m.BirthDate)
24 </div>
25 <div>
26 邮箱:
27 @Html.EditorFor(m => m.Email)
28 </div>
29 <div>
30 @Html.EditorFor(m => m.IsApprove)
31 同意相关条约
32 </div>
33 <div>
34 <input type="submit" value="注册" />
35 </div>
36 }

5、因为后面要用到客户端验证,所以这里我们先把需要引用需要的js库(在Views/Shared/_Layout.cshtml中写入):

 1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8" />
5 <meta name="viewport" content="width=device-width" />
6 <title>@ViewBag.Title</title>
7 @Styles.Render("~/Content/css")
8 @Scripts.Render("~/bundles/modernizr")
9 @Scripts.Render("~/bundles/lufy")
10 </head>
11 <body>
12
13 @RenderBody()
14
15 @Scripts.Render("~/bundles/jquery")
16 @Scripts.Render("~/bundles/jqueryval")
17 @RenderSection("scripts", required: false)
18 </body>
19 </html>

PS:为了确保正确,请读者验证下web.config中的以下属性的值是否跟笔者的一样:

三、常规验证


相信很多从事ASP.NET的开发者在对数据的验证上基本都是用的ASP.NET自带的验证控件,同时在后台还会通过N多个if语句再去判断,所以在ASP.NET
MVC的常规验证跟这个一样,唯一的区别就是错误的信息输出不需要我们自己实现了,下面我们修改Home控制器中的Index(Register reg)动作:


 1         [HttpPost]
2 public ActionResult Index(Register reg)
3 {
4 if (String.IsNullOrEmpty(reg.UserName))
5 {
6 ModelState.AddModelError("UserName", "用户名不能为空");
7 }
8 else if (reg.UserName.Length < 6)
9 {
10 ModelState.AddModelError("UserName", "用户名长度不能小于6位");
11 }
12 if (ModelState.IsValidField("BirthDate") && reg.BirthDate > DateTime.Now)
13 {
14 ModelState.AddModelError("BirthDate", "生日不能为将来的时间");
15 }
16 if (ModelState.IsValid)
17 {
18 //保存数据
19 }
20 return View();
21 }

上面我们简单的判断了用户名是否为空,长度是否小于6,以及出生日期是否填写的为将来的日期,接着我们还要在Index视图中加入@Html.ValidationSummary(),这样我们才能够看到最后的输出的错误信息,编译然后不输入任何内容点击注册之后将会出现下面的情况:

我们会发现表单压根就提交不了,这是因为客户端验证在工作。获取读者会很奇怪这节只是常规验证,这个是因为出生日期的格式是DateTime是不能为NULL的,而ASP.NET
MVC默认情况下就已经为我们做好了。随便输入123到出生日期然后点击注册,页面会反馈下面的错误信息:

第一个信息就是我们在控制器中通过if判断语句加进去的,而第二个似乎你会困惑是怎么回事,这是因为模型绑定器中会为我们进行简单的验证,比如日期不能为空,并且日期的格式要正确,这个都是默认的行为。我们可以尝试在用户名中输入123,同时出生日期输入2020/1/1,点击注册,这时候的错误信息都是我们添加的了:

读者使用过很多系统,错误信息基本上都是显示在对应的输入框的右边,在ASP.NET
MVC中一样可以判断,下面我们修改Index视图:

 1     <div>
2 用户名:
3 @Html.EditorFor(m => m.UserName)
4 @Html.ValidationMessageFor(m => m.UserName)
5 </div>
6 <div>
7 出生日期:
8 @Html.EditorFor(m => m.BirthDate)
9 @Html.ValidationMessageFor(m => m.BirthDate)
10 </div>

这个时候我们在重新提交,错误信息就到右边了。但是笔者还不打算结束掉这节,我如果限制用户名不能为100000怎么办呢?或许读者马上就能写出来,但是这个是模型级的错误,并不是针对这个字段,所以我们在Home控制器的Index方法(响应Post的那个)中继续追加:

接着修改Index视图:

然后重新编译,用户名输入100000就可以看到下面的结果:

这样我们就可以结束这节了。

四、采用注解属性的验证


上面这种方式的验证虽然简单,很多人都能够立马上手,但是看到动作中N多个if语句的确不是个滋味,在这个炎炎夏日会让人非常暴躁,这节我们就来简单的方法来解决这些问题,为我们降温,我们修改Register模型类:


 1 namespace MvcStudy.Models
2 {
3 public class Register
4 {
5 [Required(ErrorMessage="用户名必须填写")]
6 [MinLength(6,ErrorMessage="用户名长度过短")]
7 public String UserName { get; set; }
8 [DataType(DataType.Password)]
9 public String Password { get; set; }
10 [DataType(DataType.Password)]
11 [Compare("Password",ErrorMessage="密码要一致")]
12 public String RptPassword { get; set; }
13 public String Email { get; set; }
14 public DateTime BirthDate { get; set; }
15 public bool IsApprove { get; set; }
16 }
17 }

笔者在这里还判断了密码和重复密码是否相同,关于DataType可以参考笔者写的模型绑定,下面重新编译,然后打开页面测试,就可以发现这些验证都实现了,因为笔者这里默认开启了客户端验证所以在未验证通过的情况下无法提交表单。但是我们发现现有的验证注解属性没法实现显示出生日期不能为将来实现,所以下面一节我们还要学习自定义验证注解属性。

五、自定义验证注解属性


通过上节我们已经能够使用ASP.NET
MVC自带的验证属性来完成一些简单的验证,正如上节最后所说的那样,对于一部分验证自带的已经无法满足我们的需求了,那么我们就需要通过自定义的方式来解决,下面我们自定义一个注解属性来解决上节遗留下来的问题,首先我们新建一个Validation文件夹,然后在该文件夹下面新建一个FutureTimeAttribute类,代码如下所示:


 1 namespace MvcStudy.Validation
2 {
3 public class FutureTimeAttribute : ValidationAttribute
4 {
5 public override bool IsValid(object value)
6 {
7 DateTime dt = (DateTime)value;
8 if (dt != null)
9 {
10 if (dt < DateTime.Now)
11 {
12 return true;
13 }
14 }
15 return false;
16 }
17 }
18 }

接着我们就可以运用到对应的属性上面了

重新编译,然后填写一个将来的时间点击注册之后我们将会看到如下的结果:

通过这节的补充,相信大家此时此刻酷爽吗?当然还有一部分人还需要更实现更复杂的验证判断,而且是针对特定的模型类实现的,并不适合采用上面这种方式,那么下节会非常符合你的胃口。

PS:读者不仅仅可以通过继承ValidationAttribute,同时还可以继承其他现有的验证注解属性,比如RequiredAttribute等。

六、模型与验证合二为一


我们可以发现笔者之前不是显示用户名不能为100000吗,但是我并没有将这个作为注解属性而写,因为注解属性一般适合于很多地方都需要使用这种验证才适合,但是这个限制仅仅只是针对这个模型类,而其他的模型类并不需要。那么我们就需要一中能够与模型类紧密相关的验证,而解决方案就是让模型类实现IValidatableObject接口的Validate方法即可,比如下面笔者将实现限制用户名不能为100000的情况:

 1 namespace MvcStudy.Models
2 {
3 public class Register : IValidatableObject
4 {
5 [Required(ErrorMessage="用户名必须填写")]
6 [MinLength(6,ErrorMessage="用户名长度过短")]
7 public String UserName { get; set; }
8 [DataType(DataType.Password)]
9 public String Password { get; set; }
10 [DataType(DataType.Password)]
11 [Compare("Password",ErrorMessage="密码要一致")]
12 public String RptPassword { get; set; }
13 public String Email { get; set; }
14 [FutureTimeAttribute(ErrorMessage="时间不能为将来")]
15 public DateTime BirthDate { get; set; }
16 public bool IsApprove { get; set; }
17
18 public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
19 {
20 var result = new List<ValidationResult>();
21 if (UserName == "100000")
22 {
23 result.Add(new ValidationResult("用户名不能为100000"));
24 }
25 return result;
26 }
27 }
28 }

然后我们重新编译,用户名输入为100000就可以看到这个错误了:

七、客户端验证


其实前面几节一直都在使用客户端验证,本该这节是不需要的,但是我们可以发现邮箱部分还没有验证,读者可能会认为应该使用RegularExpression来验证,但是学过jquery验证库的人应该知道这个库已经自带了专门的验证,而这节就是用来手动使用这个验证的,我们打开Index视图修改邮箱部分:


 1     <div>
2 邮箱:
3 @Html.TextBoxFor(m => m.Email, new
4 {
5 data_val = "true",
6 data_val_email = "邮箱格式错误",
7 data_val_required = "请输入邮箱"
8 })
9 @Html.ValidationMessageFor(m => m.Email)
10 </div>

刷新页面,这个时候我们发现邮箱也可以验证了:

相信很多喜欢客户端开发而不是服务端开发人员来说,这种方式对于你们来说更快捷,但是对于服务端开发者来说,并不需要气馁,ASP.NET
MVC也提供对应的方法,下节我们将用服务端的方式来实现同样的效果。

八、自定义客户端验证


这里笔者就不多说废话了直接上代码,我们自己实现一个邮箱验证属性,而且还能够支持客户端验证,首先在Valudation文件夹下新建一个EmailAttribute类,并在其中写入如下代码:

 1 namespace MvcStudy.Validation
2 {
3 public class EmailAttribute : ValidationAttribute , IClientValidatable
4 {
5
6 public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
7 {
8 return new List<ModelClientValidationRule>
9 {
10 new ModelClientValidationRule{
11 ValidationType = "email",
12 ErrorMessage = "请输入正确的邮箱"
13 }
14 };
15 }
16 }
17 }

PS:为了能够符合本节,所以笔者就没有将服务端的验证代码写到其中,如果读者需要在真实场合中使用务必将服务端的验证也要加上去。

下面我们就在Email中加上这个注解属性并重新编译,我们可以看到最后页面的效果跟上一节的效果是完全一致的。

九、结束语


其实笔者并不才,但是拥有非常大的兴趣,而今已经是习惯了。每天总是要看上那么些技术方面的书,写上几段代码,当然还不少谢谢随笔和大家分享啦!

由y-z-f编写的perl脚本自动排版

ASP.NET MVC学习之模型验证篇

时间: 2024-12-25 04:44:52

ASP.NET MVC学习之模型验证篇的相关文章

ASP.NET MVC学习之模型模板篇

一.前言 如果你使用ASP.NET MVC制作后台一定会爱上它的EditorForModal.DisplayForModal和LabelForModal方法,因为这些方法可以将模型直接变成对应的标签,省了不少事,但是对于一些苛刻的人来说,一定想自定义,下面我们会先介绍如何使用,然后介绍如何自定义. 二.正文 1.输出模型 首先我们要新建一个Home控制器,对应的还要有一个Index动作,和Index视图,接着我们在Modal下新建一个Address类: 1 namespace MvcStudy.

ASP.NET MVC学习之模型绑定(1)

一.前言 下面我们将开始学习模型绑定,通过下面的知识我们将能够理解ASP.NET MVC模型的模型绑定器是如何将http请求中的数据转换成模型的,其中我们重点讲述的是表单数据. 二.正文 1.简单类型绑定 学过一定ASP.NET MVC都会为这个特点所骄傲,就是能够将表单中与同名的参数映射,这相比操作ASP.NET控件来获取值轻便了许多,但是正如上面所说的那样要同名(大小写不区分),下面我们会讲述如何自己去指定. 首先我们在HomeController(如果不存在则创建)中获取表单中的值并显示:

ASP.NET MVC学习之模型绑定(2)

3.手工调用模型绑定 很多情况下我们都是通过形参的方式接收来自http流中的数据,这看似是完美的,但是缺少了很多过程中的控制,所以我们就需要使用手工的方式进行绑定.下面我们通过一个例子来说明,首先打开Views/Home/Index.cshtml页面,并输入如下代码: 1 @{ 2 ViewBag.Title = "Index"; 3 } 4 5 @if (TempData.ContainsKey("msg")) 6 { 7 <h1> 8 @TempDa

ASP.NET MVC 4 (十) 模型验证

模型验证是在模型绑定时检查从HTTP请求接收的数据是否合规以保证数据的有效性,在收到无效数据时给出提示帮助用户纠正错误的数据. 显式模型验证 验证数据最直接的方式就是在action方法中对接收的数据验证,以下面的Model为例: public class Appointment { public string ClientName { get; set; } public DateTime Date { get; set; } public bool TermsAccepted { get; s

ASP.NET MVC学习之Ajax(完结)

一.前言 通过上面的一番学习,大家一定收获不少.但是总归会有一个结束的时候,但是这个结束也意味着新的开始. 如果你是从事ASP.NET开发,并且也使用了第三方控件,那么一定会觉得ASP.NET开发ajax十分的简单,而ASP.NET MVC学习到现在页面都是刷新的,所以这节就是ASP.NET MVC的最后一节,通过这节的学习我们将能够实现通过ajax提交表单,下面我们开始继续学习. 二.准备工作 1.首先确保引用了以下js库在_Layout中: 2.新建一个HomeController,然后在其

ASP.NET MVC学习---(九)权限过滤机制(完结篇)

相信对权限过滤大家伙都不陌生 用户要访问一个页面时 先对其权限进行判断并进行相应的处理动作 在webform中 最直接也是最原始的办法就是 在page_load事件中所有代码之前 先执行一个权限判断的方法 至于其专业的权限机制这里不做讨论 想要了解的同学可以自行google之 或者点击进入: webform专业的权限验证机制 那么mvc中是如何实现权限验证的? 据我们所知 mvc中是根据路由配置来请求控制器类中的一个方法 并没有webform中的page_load方法 难道我们要在每个actio

ASP.NET MVC学习之控制器篇

一.前言 许久之后终于可以继续我的ASP.NET MVC连载了,之前我们全面的讲述了路由相关的知识,下面我们将开始控制器和动作的讲解. ASP.NET MVC学习之路由篇幅(1) ASP.NET MVC学习之路由篇幅(2) ASP.NET MVC学习之路由篇幅(3) 二.正文 1.IController的使用 这个接口可能很多人都没有使用过,但是我们常用的Controller类实现了这个接口,而且只要实现这个接口就可以作为一个控制器,当然很多的内部的处理就要我们自己去做了. 下面我利用ICont

ASP.NET MVC学习之过滤器篇(2)

下面我们继续之前的ASP.NET MVC学习之过滤器篇(1)进行学习. 3.动作过滤器 顾名思义,这个过滤器就是在动作方法调用前与调用后响应的.我们可以在调用前更改实际调用的动作,也可以在动作调用完成之后更改最终返回的结果,当然很多人一定不太明白这个到底可以干什么, 下面我们举一个比较实际的例子: 相信理解过网站的安全的一定知道跨站请求(CSRF具体可以自行百度,这里我就不去解释了),当然也有解决方案,那就是给页面中增加一个识别码,当页面进行POST请求时,首先判断识别码是否正确, 如果正确则继

ASP.NET MVC学习之视图篇(2)

继ASP.NET MVC学习之视图(1)学习 4.HTML辅助器 虽然在ASP.NET MVC中我们已经摆脱了ASP.NET的控件,但是对于页面中需要循环标签的情况依然还是存在,可能很多人认为用foreach就可以完成,但是这个仅仅只是针对单个循环,如果多个循环中都要使用到同样的标签呢?下面笔者就介绍两种方式让我们事半功倍. 首先是针对单个页面的内联辅助器,如果我们遇到只要在单个页面中不断使用的标签的时候,这个方式非常的轻便,比如下面的代码根据文本内容和样式类生成li标签的辅助器(Views/H