ASP.NET MVC Model验证(三)
上篇中说到在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级验证错误信息。