.net使用FluentValidation进行服务端验证。

      背景

      最近使用asp.mvc 做一个在线口语系统项目,在服务端验证问题遇到了一些小问题。

     自己根据数据库表user定义一个数据库表实体对象UserDbEntity

 1     [Table("User")]
 2     public class UserDbEntity : DbEntityModelBase
 3     {
 4         [Description("用户名")]
 5         [Required(ErrorMessage="*")]
 6         public string Name
 7         {
 8             get;
 9             set;
10         }
11         [Description("邮箱")]
12         [Required]
13         public string Email
14         {
15             get;
16             set;
17         }
18         [Description("密码")]
19         [Required(ErrorMessage="*")]
20         public string Pwd
21         {
22             get;
23             set;
24         }
25         [Description("确认密码,数据库不存在该字段")]
26         [Required(ErrorMessage = "*")]
27         public string SecondPwd
28         {
29             get;
30             set;
31         }
32 
33         [Description("真实姓名")]
34         [Required]
35         public string TrueName
36         {
37             get;
38             set;
39         }
40 
41         [Description("邮箱是否已激活,长度为1")]
42         public int Actived
43         {
44             get;
45             set;
46         }
47     }
48 
49     /// <summary>
50     /// 所有DbEntityModel项目中的实体必须继承DbEntityModelBase或其子类,使用supperType模式控制共有子类的行为或者状态,此项目中的类根据数据库基本表或者视图保持基本一致
51     /// </summary>
52    public abstract class DbEntityModelBase
53     {
54         [Description("Guid标识")]
55         public string GuidMark
56         {
57             get;
58             set;
59         }
60         [Description("自增Id列")]
61         public int Id
62         {
63             get;
64             set;
65         }
66        [Description("排序,倒序")]
67         public int Sort
68         {
69             get;
70             set;
71         }
72     }
View Code

  在前端页面有一个登陆页面直接使用UserDbEntity实体对象UserDbEntity

 1      <form id="login_form" style="padding: 10px 20px 10px 40px;" action="Login" method="post">
 2         <p>
 3             <em>用户名</em>@Html.EditorFor(model=>model.User.Name) @Html.ValidationMessageFor(model=>model.Name)</p>
 4         <p>
 5             <em>密码</em>@Html.PasswordFor(model=>model.Pwd) @Html.ValidationMessageFor(model=>model.User.Pwd)</p>
 6         <div style="padding: 5px; text-align: center;">
 7             <a href="#" onclick="$('#login_form').submit();return false" class="easyui-linkbutton" icon="icon-ok">登录</a>
 8              <a href="#" onclick="$('#login_form')[0].reset()" class="easyui-linkbutton"
 9                     icon="icon-cancel">重填</a>
10         </div>
11         </form>
View Code

 

 在控制器中对输入进行验证

 1         [HttpPost]
 2         public ActionResult Login(UserDbEntity loginModel)
 3         {
 4             bool loginFlag = false;
 5             string name = loginModel.Name;
 6             string pwd = loginModel.Pwd; ;
 7             if(ModelState.IsValid){
 8                 return Login();
 9             }
10             var user = new UserDbEntity();
11 
12             using (var scope = IocRegisterBLL.ContainerBLLComponent.BeginLifetimeScope())
13             {
14                 var userBLL = scope.Resolve<UserBLL>();
15                 loginFlag = userBLL.AdminLogin(name, pwd, out user);
16             }
17 
18             if (loginFlag)
19             {
20                 Session[C_LogOnSession] = user;
21                 return Index();
22             }
23             else
24             {
25                 return Login();
26             }
27         }
View Code

ModelState.IsValid 永远是false。因为我们的表单对email输入,email是空,用mvc服务端验证机制验证,永远不能通过。

  

    遇到问题,我们就要思考。现在我有两种思路解决问题。

 第1种方法是。 为每个页面制定一个ViewModel, 然后这个ViewModel在使用DataAnnotations ,最后使用mvc服务端的验证机制。 当然这个方法也是大项目使用最多的方法。 ViewModel 和UserDbEntity之间的转化时候AutoMapper 进行DTO。 但这个方法我不太喜欢,因为我觉得我这个项目属于中小项目,没必要每个页面制定一个ViewModel。 于是我找到了第2种方法。

第2种方法。使用FluentValidation验证。使用FluentValidation 为login页面 对 UserDbEntity 写一个验证类。

 

使用FluentValidation 解决背景介绍中遇到的问题

1 引用: FluentValidation.dll  ,可以直接 Nuget ,Install-Package FluentValidation。

2. 编写UserLoginValidator类

1    public class UserLoginValidator: AbstractValidator<UserDbEntity>
2     {
3         public UserLoginValidator()
4         {
5             RuleFor(u=>u.Name).NotNull().WithMessage("用户名不能为空");
6             RuleFor(u => u.Pwd).NotNull().WithMessage("密码不能为空");
7         }
8     }
View Code

3、在login controller使用 UserLoginValidator类进行验证。

 1      [HttpPost]
 2         public ActionResult Login(UserDbEntity loginModel)
 3         {
 4             bool loginFlag = false;
 5             string name = loginModel.Name;
 6             string pwd = loginModel.Pwd;
 7             UserLoginValidator validInstance = new UserLoginValidator();
 8             if(!validInstance.Validate(loginModel).IsValid){
 9                 return Login();
10             }
11             var user = new UserDbEntity();
12 
13             using (var scope = IocRegisterBLL.ContainerBLLComponent.BeginLifetimeScope())
14             {
15                 var userBLL = scope.Resolve<UserBLL>();
16                 loginFlag = userBLL.AdminLogin(name, pwd, out user);
17             }
18 
19             if (loginFlag)
20             {
21                 Session[C_LogOnSession] = user;
22                 return Index();
23             }
24             else
25             {
26                 return Login();
27             }
28         }
View Code

这样就能解决我在背景中碰到的问题。 如果项目中其他页面也用到到UserDbEntity,但验证规则需要个性化,你也可以另外针对UserDbEntity写另外一个Validator类。

这样就不必要对给个页面制定一个ViewModel了。

 

推荐在项目中使用FluentValidation进行服务端验证

 FluentValidation 在个github上的地址 https://github.com/JeremySkinner/FluentValidation。FluentValidation的链式方法调用,写验证非常的流畅。可以为你在项目中写服务端验证逻辑节省不少时间。

 

 



 

posted @ 2015-07-12 11:16  swan.huang  阅读(1820)  评论(1编辑  收藏  举报