天天看点

ASP.NETMVC Model验证(三)

ASP.NETMVC Model验证(三)

前言

上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的Model验证是在哪个具体的方法中来执行的,本篇的主题就是模拟一下默认的实现,自定义个Model绑定器继承自DefaultModelBinder类型,并且重写某些个重要的方法。

Model验证

Model验证简单运用示例

ModelValidator使用生成过程

自定义实现DefaultModelBinder进行验证

自定义ModelValidatorProvider 和ModelValidator 

ValidationAttribute特性类使用

自定义ValidationAttribute特性类的示例实现

以下用到的示例正是修改自ASP.NET MVC Model验证(一)篇幅中的示例,这里就不多说什么了,开始直接贴代码。

首先是ViewModel的定义,代码1-1。

代码1-1

1

2

3

4

5

6

7

8

9

10

11

<code>namespace</code> <code>MvcApplication.Models</code>

<code>{</code>

<code>    </code><code>public</code> <code>class</code> <code>RegistrationInformation</code>

<code>    </code><code>{</code>

<code>        </code><code>public</code> <code>string</code> <code>ID { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>string</code> <code>UserID { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>string</code> <code>Password1 { </code><code>get</code><code>;</code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>string</code> <code>Password2 { </code><code>get</code><code>;</code><code>set</code><code>; }</code>

<code>        </code><code>public</code> <code>string</code> <code>Name { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>    </code><code>}</code>

<code>}</code>

控制器的定义,代码1-2:

代码1-2

<code>    </code><code>public</code> <code>class</code> <code>ModelValidatorController: Controller</code>

<code>        </code><code>public</code> <code>ActionResult Index()</code>

<code>        </code><code>{</code>

<code>            </code><code>returnView(</code><code>new</code> <code>Models.RegistrationInformation());</code>

<code>        </code><code>}</code>

<code>        </code><code>public</code> <code>ActionResult ModelValidator(RegistrationInformation regInfo)</code>

<code>            </code><code>returnView(regInfo);</code>

控制器方法对应视图定义,代码1-3:

代码1-3-1

Index视图

@model MvcApplication.Models.RegistrationInformation

@{

    ViewBag.Title = "Index";

}

&lt;h2&gt;Index&lt;/h2&gt;

@using (Html.BeginForm("ModelValidator","ModelValidator"))

{

    &lt;p&gt;用户注册ID:@Html.EditorFor(m=&gt;m.ID)&lt;/p&gt;

    &lt;p&gt;用户名:@Html.EditorFor(m=&gt;m.UserID)&lt;/p&gt;

    &lt;p&gt;登录密码:@Html.EditorFor(m=&gt;m.Password1)&lt;/p&gt;

    &lt;p&gt;再次输入域密码:@Html.EditorFor(m=&gt;m.Password2)&lt;/p&gt;

    &lt;p&gt;姓名:@Html.EditorFor(m=&gt;m.Name)&lt;/p&gt;

    &lt;input type="submit" value="提交" /&gt;

代码1-3-2

ModelValidator视图

    ViewBag.Title = "ModelValidator";

&lt;h2&gt;ModelValidator&lt;/h2&gt;

@Html.ValidationSummary(true)

&lt;p&gt;用户注册ID:@Html.EditorFor(m =&gt; m.ID)

@Html.ValidationMessageFor(m=&gt;m.ID)

&lt;/p&gt;

&lt;p&gt;用户名:@Html.EditorFor(m =&gt; m.UserID)

@Html.ValidationMessageFor(m=&gt;m.UserID)&lt;/p&gt;

&lt;p&gt;登录密码:@Html.EditorFor(m =&gt; m.Password1)

@Html.ValidationMessageFor(m=&gt;m.Password1)

&lt;p&gt;再次输入域密码:@Html.EditorFor(m =&gt; m.Password2)

@Html.ValidationMessageFor(m=&gt;m.Password2)

&lt;p&gt;姓名:@Html.EditorFor(m=&gt;m.Name)&lt;/p&gt;

前面所示的就是把示例演示所需的定义好,这个时候运行会发现,只不过是一个页面传值而已,什么都没有发生。现在我们来定义一下自定义的Model绑定器继承自DefaultModelBinder类型。

代码1-4

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

<code>    </code><code>public</code> <code>class</code> <code>MyCustomDefaultModelBinder: DefaultModelBinder</code>

<code>        </code><code>protectedoverride voidSetProperty(ControllerContextcontrollerContext, ModelBindingContextbindingContext, PropertyDescriptorpropertyDescriptor, </code><code>object</code> <code>value)</code>

<code>            </code><code>base</code><code>.SetProperty(controllerContext,bindingContext, propertyDescriptor, value);</code>

<code> </code> 

<code>            </code><code>switch</code><code>(propertyDescriptor.Name)</code>

<code>            </code><code>{</code>

<code>                </code><code>case</code><code>"ID"</code><code>:</code>

<code>                    </code><code>if</code><code>(</code><code>string</code><code>.IsNullOrEmpty((</code><code>string</code><code>)value)|| (</code><code>string</code><code>)value == </code><code>""</code><code>)</code>

<code>                    </code><code>{</code>

<code>                       </code><code>bindingContext.ModelState.AddModelError(</code><code>"ID"</code><code>,</code><code>"请输入ID,ID不能为空!"</code><code>);</code>

<code>                    </code><code>}</code>

<code>                    </code><code>break</code><code>;</code>

<code>                </code><code>case</code><code>"UserID"</code><code>:</code>

<code>                       </code><code>bindingContext.ModelState.AddModelError(</code><code>"UserID"</code><code>,</code><code>"请输入用户账户,用户账户不能为空!"</code><code>);</code>

<code>                </code><code>case</code><code>"Password1"</code><code>:</code>

<code>                       </code><code>bindingContext.ModelState.AddModelError(</code><code>"Password1"</code><code>,</code><code>"请输入登录密码,登录密码不能为空!"</code><code>);</code>

<code>                </code><code>case</code><code>"Password2"</code><code>:</code>

<code>                        </code><code>bindingContext.ModelState.AddModelError(</code><code>"Pssword2"</code><code>, </code><code>"请再次输入密码,密码不能为空!"</code><code>);</code>

<code>                </code><code>case</code><code>"Name"</code><code>:</code>

<code>            </code><code>}</code>

<code>        </code><code>protectedoverride voidOnModelUpdated(ControllerContextcontrollerContext, ModelBindingContextbindingContext)</code>

<code>            </code><code>base</code><code>.OnModelUpdated(controllerContext,bindingContext);</code>

<code>            </code><code>Models.RegistrationInformationregInfo = bindingContext.Model </code><code>as</code> <code>Models.RegistrationInformation;</code>

<code>            </code><code>if</code><code>(bindingContext.ModelState[</code><code>"Password1"</code><code>].Errors.Count== 0 &amp;&amp; bindingContext.ModelState[</code><code>"Password2"</code><code>].Errors.Count== 0)</code>

<code>                </code><code>if</code><code>(regInfo.Password1 != regInfo.Password2)</code>

<code>                </code><code>{</code>

<code>                   </code><code>bindingContext.ModelState.AddModelError(</code><code>"Password2"</code><code>,</code><code>"请重新输入密码,与上次输入密码不同"</code><code>);</code>

<code>                </code><code>}</code>

<code>            </code><code>if</code><code>(</code><code>string</code><code>.Compare(regInfo.Name, </code><code>"jinyuan"</code><code>, </code><code>true</code><code>)==0)</code>

<code>               </code><code>bindingContext.ModelState.AddModelError(</code><code>""</code><code>,</code><code>"您输入的名称违法了,立即更改不然查水表"</code><code>);</code>

代码1-4中,我们重写了SetProperty()方法,从上篇的知识中得知,这个方法是在PropertyDescriptor类型的集合中遍历执行的,所以每次进入方法内部的只是个Model属性,而在SetProperty()方法内部的Model验证判断逻辑和ASP.NETMVC Model验证(一)篇幅的一样。

而在OnModelUpdated()方法中,我们首先获取了示例代码1-1中定义的ViewModel类型实例,这里有的朋友可能会问为什么不在SetProperty()方法中也这样使用,而是使用PropertyDescriptor类型的参数来进行验证操作,因为在SetProperty()方法执行的期间并没有对ViewModel完全的赋值,所以不能那样直接获取实例来使用。接着上面的说,在此之后从当前的绑定上下文的ModelState属性中获取判断密码1和密码2是否存在属性验证级的错误信息,没有的话将会对它们进行等值验证,正如上面代码所示的那样,随之验证Name的时候我将错误信息添加的键值为””,这表示默认为Model级验证错误信息。

所需要做的验证都做完了,注册我们的自定义绑定器到系统中,在Global.asax文件的Application_Start()中添加代码1-5.

代码1-5

<code>ModelBinders.Binders.Add(</code><code>typeof</code><code>(Models.RegistrationInformation),</code><code>new</code> <code>Binders.MyCustomDefaultModelBinder());</code>

最后我们看一下效果图,图1表示为起初展示的页面,在我输入一部分的信息过后,点击提交过后页面会跳转到图2,并且执行完验证显示出验证后的错误信息。

图1

<a href="http://s3.51cto.com/wyfs02/M01/3B/A2/wKiom1O-krOSb5L2AAEL1TlPDiQ637.jpg" target="_blank"></a>

图2

<a href="http://s3.51cto.com/wyfs02/M00/3B/A2/wKioL1O-krLgdMM1AAHGT3AcGlE253.jpg" target="_blank"></a>

大家可以动手试一试,到这里说明了一种验证方式,将在下篇为大家讲解MVC框架提供给我们的正儿八经用来执行验证的类型的一些相关类型,以及一些简单的示例,这样我们就不在使用Model绑定器来执行验证了,看起来绑定器有点不务正业。

     本文转自jinyuan0829 51CTO博客,原文链接:http://blog.51cto.com/jinyuan/1436861,如需转载请自行联系原作者