前言

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

 

 

 

model验证

model验证简单运用示例

modelvalidator使用生成过程

自定义实现defaultmodelbinder进行验证

自定义modelvalidatorprovider 和modelvalidator 

validationattribute特性类使用

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

 

 

自定义实现defaultmodelbinder进行验证

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

 

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

 

代码1-1

 

复制代码

namespace mapplication.models

 

{

 

    public class registrationinformation

 

    {

 

        public string id { get; set; }

 

        public string userid { get; set; }

 

        public string password1 { get; set; }

 

        public string password2 { get; set; }

 

        public string name { get; set; }

 

    }

 

}

复制代码

 

 

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

 

代码1-2

 

 

 

复制代码

   public class modelvalidatorcontroller : controller

 

    {

 

        public actionresult index()

 

        {

 

            return view(new models.registrationinformation());

 

        }

 

        public actionresult modelvalidator(registrationinformation reginfo)

 

        {

 

            return view(reginfo);

 

        }

 

    }

复制代码

 

 

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

 

代码1-3-1

 

index视图

 

复制代码

@model mvcapplication.models.registrationinformation

 

@{

 

    viewbag.title = “index”;

 

}

 

<h2>index</h2>

 

@using (html.beginform(“modelvalidator”,”modelvalidator”))

 

{

 

    <p>用户注册id:@html.editorfor(m=>m.id)</p>

 

    <p>用户名:@html.editorfor(m=>m.userid)</p>

 

    <p>登录密码:@html.editorfor(m=>m.password1)</p>

 

    <p>再次输入域密码:@html.editorfor(m=>m.password2)</p>

 

    <p>姓名:@html.editorfor(m=>m.name)</p>

 

    <input type=”submit” value=”提交” />

 

}

复制代码

代码1-3-2

 

modelvalidator视图

 

复制代码

@model mvcapplication.models.registrationinformation

 

@{

 

    viewbag.title = “modelvalidator”;

 

}

 

<h2>modelvalidator</h2>

 

@html.validationsummary(true)

 

<p>用户注册id:@html.editorfor(m => m.id)

 

@html.validationmessagefor(m=>m.id)

 

</p>

 

<p>用户名:@html.editorfor(m => m.userid)

 

@html.validationmessagefor(m=>m.userid)</p>

 

<p>登录密码:@html.editorfor(m => m.password1)

 

@html.validationmessagefor(m=>m.password1)

 

</p>

 

<p>再次输入域密码:@html.editorfor(m => m.password2)

 

@html.validationmessagefor(m=>m.password2)

 

</p>

 

<p>姓名:@html.editorfor(m=>m.name)</p>

复制代码

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

 

代码1-4

 

复制代码

public class mycustomdefaultmodelbinder : defaultmodelbinder

    {

        protected override void setproperty(controllercontext controllercontext, modelbindingcontext bindingcontext, propertydescriptor propertydescriptor, object value)

        {

            base.setproperty(controllercontext, bindingcontext, propertydescriptor, value);

 

            switch (propertydescriptor.name)

            {

                case “id”:

                    if (string.isnullorempty((string)value) || (string)value == “”)

                    {

                        bindingcontext.modelstate.addmodelerror(“id”, “请输入id,id不能为空!”);

                    }

                    break;

                case “userid”:

                    if (string.isnullorempty((string)value) || (string)value == “”)

                    {

                        bindingcontext.modelstate.addmodelerror(“userid”, “请输入用户账户,用户账户不能为空!”);

                    }

                    break;

                case “password1”:

                    if (string.isnullorempty((string)value) || (string)value == “”)

                    {

                        bindingcontext.modelstate.addmodelerror(“password1”, “请输入登录密码,登录密码不能为空!”);

                    }

                    break;

                case “password2”:

                    if (string.isnullorempty((string)value) || (string)value == “”)

                    {

                        bindingcontext.modelstate.addmodelerror(“pssword2”, “请再次输入密码,密码不能为空!”);

                    }

                    break;

                case “name”:

                    break;

            }

        }

 

        protected override void onmodelupdated(controllercontext controllercontext, modelbindingcontext bindingcontext)

        {

            base.onmodelupdated(controllercontext, bindingcontext);

            models.registrationinformation reginfo = bindingcontext.model as models.registrationinformation;

            if (bindingcontext.modelstate[“password1”].errors.count == 0 && bindingcontext.modelstate[“password2”].errors.count == 0)

            {

                if (reginfo.password1 != reginfo.password2)

                {

                    bindingcontext.modelstate.addmodelerror(“password2”, “请重新输入密码,与上次输入密码不同”);

                }

            }

            if (string.compare(reginfo.name, “jinyuan”, true)==0)

            {

                bindingcontext.modelstate.addmodelerror(“”, “您输入的名称违法了,立即更改不然查水表”);

            }

        }

    }

复制代码

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

 

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