(一)基本验证
通过htmlhelper来验证。
以Customer为例:
在创建(Create)视图中,如果应用了验证:
<%
=
Html.ValidationSummary(
"
Create was unsuccessful.
Please correct the errors
and
try again.
"
) %>
<
% using (Html.BeginForm(
"
Create
"
,
"
Customer
"
,
FormMethod.Post,
new
{enctype
=
"
application/x-www-form-urlencoded
"
}))
{
%>
<
fieldset
>
<
legend
>
Fields
</
legend
>
<
p
>
<
label
for
="FirstName"
>
FirstName:
</
label
>
<%
=
Html.TextBox(
"
FirstName
"
)
%>
<%
=
Html.ValidationMessage(
"
FirstName
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
label
for
="LastName"
>
LastName:
</
label
>
<%
=
Html.TextBox(
"
LastName
"
)
%>
<%
=
Html.ValidationMessage(
"
LastName
"
,
"
*
"
)
%>
</
p
>
<
p
>
<
input
type
="submit"
value
="Create"
/>
</
p
>
</
fieldset
>
<%
}
%>
以名字(FirstName)与姓氏(LastName)来说,
<%
=
Html.TextBox(
"
FirstName
"
)
%>
<%
=
Html.ValidationMessage(
"
FirstName
"
,
"
*
"
)
%>
通过helper的ValidationMessage来验证FirstName文本框,然后如果验证不通过,则文本框后加显示*符号(就像平常注册的一样,必填项有些类似,当然做为字符串,可以改的)
然后在控制器的动作中,通过ModelState来验证:
if
(customer.FirstName
==
string
.Empty)
{
ModelState.AddModelError(
"
FirstName
"
,
"
名字不能为空!
"
);
}
if
(customer.LastName
==
string
.Empty)
{
ModelState.AddModelError(
"
LastName
"
,
"
姓氏不能为空!
"
);
}
if
(Convert.ToInt32(customer.FirstName)
>
10
)
{
ModelState.AddModelError(
"
FirstName
"
,
"
名字不能大于!
"
);
}
if
(
!
ModelState.IsValid)
{
return
View();
}
这个ModelState是Controller的一个属性:
public
ModelStateDictionary ModelState
{
get
{
return
base
.ViewData.ModelState;
}
}
从这里可以看出:控制器的ModelState属性其实是ViewData的一个属性。看来ViewData用处真大(Model部分其实也是放到了这个属性中)。而ViewData是一个ViewDataDictionary 类型的。然后,这个类型的一个属性:就是ModelState,这个属性就是一个ModelStateDictionary 类型。它的方法很多,其中之一就是:
public
void
AddModelError(
string
key,
string
errorMessage)
{
this
.GetModelStateForKey(key).Errors.Add(errorMessage);
}
就是程序中用到的。其中GetModelStateForKey方法是得到一个ModelState类实例,ModelState类定义为:
public
class
ModelState
{
//
Fields
private
ModelErrorCollection _errors;
[CompilerGenerated]
private
ValueProviderResult
<
Value
>
k__BackingField;
//
Methods
public
ModelState();
//
Properties
public
ModelErrorCollection Errors {
get
; }
public
ValueProviderResult Value { [CompilerGenerated]
get
; [CompilerGenerated]
set
; }
}
当调用ModelState.AddModelError方法时:
·调用Controller的ModelState属性
·调用Controller的ModelState属性就是调用Controller的ViewData属性的ModelState
·其实调用的就是ViewDataDictionary类的ModelState属性
·当添加错误信息时,就是调用ModelState属性的AddModelError方法,
其中ModelState属性是ModelStateDictionary类型
·当添加错误信息时,就是向ModelState类实例中Errors属性中添加kv对,也就是对ModelErrorCollection
添加错误信息
然后再提一下IsValid属性:
public
bool
IsValid
{
get
{
return
this
.Values.All
<
ModelState
>
(
delegate
(ModelState modelState)
{
return
(modelState.Errors.Count
==
0
);
});
}
}
这下就一目了然了:验证数据后,会在ModelState
当Post提交过来的数据被验证时,当有错误信息时,被添加到ModelState类实例的ModelErrorCollection集合属性中,然后控制器的ModelState属性的Values属性(ModelState类型),如果这个ModelState中的错误的信息的数目为0时,则验证通过,否则验证不通过。
当验证不通过时,不会执行创建动作中的IsValid之后的逻辑,而直接返回视图。这时,错误信息已经添加到了控制器的ViewData中。然后,在视图中显示。
(二)通过实现IDataErrorInfo接口
IDataErrorInfo 接口定义:
public
interface
IDataErrorInfo
{
//
Properties
string
Error {
get
; }
string
this
[
string
columnName] {
get
; }
}
如果要实现这个接口:
·在partial类型的类实体中继承这个接口
·实现这个接口
·对数据进行验证时,只要实现[On属性Changing]即可
例如:我是直接在LinqToSql文件的Customer类中添加的接口(因为做了一个partial类,在别的地方写也是可以的,它表示可分写。)
public
partial
class
Customer : INotifyPropertyChanging,
INotifyPropertyChanged, IDataErrorInfo
实现部分为:
#region
IDataErrorInfo 成员
private
Dictionary
<
string
,
string
>
_errors
=
new
Dictionary
<
string
,
string
>
();
partial
void
OnFirstNameChanging(
string
value)
{
if
(value.Trim().Length
==
0
)
_errors.Add(
"
FirstName
"
,
"
名字不能为空.
"
);
else
{
if
(Convert.ToInt32(value.Trim())
>
10
)
_errors.Add(
"
FirstName
"
,
"
不能大于10
"
);
}
}
partial
void
OnLastNameChanging(
string
value)
{
if
(value.Trim().Length
==
0
)
_errors.Add(
"
LastName
"
,
"
姓氏不能为空.
"
);
}
public
string
Error
{
get
{
return
string
.Empty;
}
}
public
string
this
[
string
columnName]
{
get
{
if
(_errors.ContainsKey(columnName))
return
_errors[columnName];
return
string
.Empty;
}
}
#endregion
这部分相当容易实现,一个Error属性,一个实现索引,添加对验证字段(文本框)的方法。即可,然后在控制器中:
//if (customer.FirstName == string.Empty)
//{
// ModelState.AddModelError("FirstName", "名字不能为空!");
//}
这些部分就可以不要了。