这篇说一下数据注释验证(Data Annotation Validators)
这种验证方式在1.0里是不被支持的,但在.net4.0和2.0中会被支持。所以如果要在1.0中使用(我用的是vs2008和mvc 1.0),要一些准备工作:
先要添加两个库文件:
·Microsoft.Web.Mvc.DataAnnotations.dll
·System.ComponentModel.DataAnnotations.dll
这两个都要到网站去下载
http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471
下载Data Annotations Model Binder Sample 这个(Recommended default)
下载下来后,启动项目,然后生成库文件,就可以在bin/debug里找到这个文件了。
如果不使用下载的System.ComponentModel.DataAnnotations.dll这个库,而使用3.5的,会出现版本冲突。
在工程里添加对这两个库的引用,且在Global.asax文件中添加(黑体部分):
protected
void
Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders.DefaultBinder
=
new
Microsoft.Web.Mvc.DataAnnotations.DataAnnotationsModelBinder();
}
这种验证类包含4类修饰:
Range(范围):验证属性的范围值
RegularExpression(正则表达式):以正则表达式来验证属性值(指导中这个词写错了)
Required(不为空):验证属性不为空
StringLength(字串长度):验证字串属性最大长度
其中它们的基类是:Validation。有时候如果自定义修饰标签,可以从这个类派生
现在还以Customer为例:
[Required(ErrorMessage
=
"
名字不能为空
"
)]
[RegularExpression(
@"
\d{1}
"
,ErrorMessage
=
"
不能大于10
"
)]
[Column(Storage
=
"
_FirstName
"
, DbType
=
"
VarChar(50)
"
)]
public
string
FirstName
{
……
}
[Required(ErrorMessage
=
"
姓氏不能为空
"
)]
[Column(Storage
=
"
_LastName
"
, DbType
=
"
VarChar(50)
"
)]
public
string
LastName
{
……
}
这里只贴一部分。因为我这是直接在dbml代码文件里加的,所以多出1行修饰。其中加粗部分为数据注释验证(修饰标签)
在前台的效果如下:
有些情况下这种验证方式比较好,但在有些情况下这种验证方式并不适合,所以要在不同的环境情况下使用适当的验证方式。
控制器动作中的验证剥离
这里将控制器动作中的验证(一堆的if语句)分离开来,而动作中只判断Customer。
(一)到方法
在控制器中添加:
private
ModelStateDictionary _modelState;
private
bool
ValiCustomer(Customer customer,ModelStateDictionary modelState)
{
_modelState
=
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
"
,
"
名字不能大于!
"
);
}
return
_modelState.IsValid;
}
然后,在Create动作中:
if
(
!
ValiCustomer(customer,
this
.ModelState))
{
return
View();
}
return
RedirectToAction(
"
Index
"
);
这在一定程度上实现了分离
(二)指导中的分离
在提供的指导教程中,把验证做为单独的服务层来做的。而且是在创建时验证。
现在按指导中的例子,把验证做为单独的服务层来做,但不在创建时验证,而是在创建前验证。
public
interface
ICustomer
{
bool
CreateProduct(Customer customerToCreate);
}
public
class
ValiService : ICustomer
{
private
ModelStateDictionary _modelState;
public
ValiService(ModelStateDictionary modelState)
{
_modelState
=
modelState;
}
public
bool
CreateProduct(Customer customerToCreate)
{
if
(customerToCreate.FirstName
==
string
.Empty)
{
_modelState.AddModelError(
"
FirstName
"
,
"
名字不能为空!
"
);
}
if
(customerToCreate.LastName
==
string
.Empty)
{
_modelState.AddModelError(
"
LastName
"
,
"
姓氏不能为空!
"
);
}
if
(Convert.ToInt32(customerToCreate.FirstName)
>
10
)
{
_modelState.AddModelError(
"
FirstName
"
,
"
名字不能大于10!
"
);
}
return
_modelState.IsValid;
}
}
在动作中:
控制器构造器有动作:
public
CustomerController()
{
_service
=
new
ValiService(
this
.ModelState);
}
if
(
!
_service.CreateProduct(customer))
return
View();
return
RedirectToAction(
"
Index
"
);
当建立mvc应用程序时,应该不要把数据库逻辑放在控制器的动作中进行。对于其它的业务逻辑也要尽量参照这个原则。控制器的动作只用来加载模型,返回视图。对于加载的模型要一次到位(自己这样理解)。