.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的链式方法调用,写验证非常的流畅。可以为你在项目中写服务端验证逻辑节省不少时间。

 

 



 

你可能感兴趣的:(validation)