[EntLib]微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介:

   前端时间花了1个多星期的时间写了使用jQuery.Validate进行客户端验证,但是那仅仅是客户端的验证,在开发项目的过程中,客户端的信息永远是不可信的,所以我们还需要在服务器端进行服务器端的验证已保证数据的正确,今天我继续企业库的学习之路,主要介绍企业库中的Validation模块如何对数据进行验证。

本文的主要内容有以下三点:

1、根据本项目进行实体验证。

2、使用Validation提供的ASP.NET控件将实体验证和UI层页面验证联系起来

3、简单分析下Validation.Integration.Aspnet实现逻辑

 

文章开始前的废话

我学习微软企业库都是首先查看企业库提供的HOL(Microsoft Enterprise Library 5.0 - Hands On Labs),里面为企业库的每个模块编写了例子,是非常好的学习材料,而其中的Validation模块的例子是最多的,足足有14个(由此可见Validation模块在企业库中的分量),我看了下,基本上将Validation的各个方面使用方法都介绍了一遍,想学习的朋友可以认真的学习下。

 

第一点:根据本项目进行实体验证

这个项目是一个小型的学生信息管理系统(就是班级和学生简单管理,都不好意思叫系统),主要有班级、学生、科目3个类,我们现在需要通过企业库的Validation模块为这3个类加上验证。

在前几篇文章中,我已经将企业库的Validation模块的各种验证器基本信息进行了介绍,大家可以前往查看

我这边就是将student类进行了简单的验证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[StringLengthValidator(1, 16,
     MessageTemplate = "登录ID的长度必须在{3}-{5}之间!" )]
//MessageTemplateResourceType = typeof(EntLibStudy.Model.Properties.Resources),
//MessageTemplateResourceName = "SidMessage")]
public  string  Sid
{
     get ;
     set ;
}
[StringLengthValidator(1, 16,
     MessageTemplateResourceType = typeof (EntLibStudy.Model.Properties.Resources),
     MessageTemplateResourceName = "PasswordMessage" )]
public  string  Password
{
     get ;
     set ;
}
[StringLengthValidator(1, 16,
     MessageTemplateResourceType = typeof (EntLibStudy.Model.Properties.Resources),
     MessageTemplateResourceName = "NameMessage" )]
public  string  Name
{
     get ;
     set ;
}

这里我就是将Sid、Password和Name进行必须输入验证。

 

第二点:使用Validation提供的ASP.NET控件将实体验证和UI层页面验证联系起来

在Validation模块中企业库为我们提供了一个子模块——ASP.NET控件用来和Validation模块联合起来进行客户端+服务器端的验证。

我们在页面上放上一个PropertyProxyValidator控件,并指定要验证的控件、对应的实体类型及属性名,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
< tr >
     < td  align="right">
         登录ID:
     </ td >
     < td >
         < asp:TextBox  runat="server" ID="txtSid" />
         < cc1:PropertyProxyValidator  ID="PropertyProxyValidator1" runat="server"
             ControlToValidate="txtSid" PropertyName="Sid"
             SourceTypeName="EntLibStudy.Model.Student,EntlibStudy.Model" ValidationGroup="test"></ cc1:PropertyProxyValidator >
     </ td >
</ tr >
< tr >
     < td  align="right">
         密码:
     </ td >
     < td >
         < asp:TextBox  runat="server" ID="txtPwd" TextMode="Password" />
         < cc1:PropertyProxyValidator  ID="PropertyProxyValidator2" runat="server"
             ControlToValidate="txtPwd" PropertyName="Password"
             SourceTypeName="EntLibStudy.Model.Student,EntlibStudy.Model" ValidationGroup="test"></ cc1:PropertyProxyValidator >
     </ td >
</ tr >
< tr >
     < td  align="right">
         姓名:
     </ td >
     < td >
         < asp:TextBox  runat="server" ID="txtName" />
         < cc1:PropertyProxyValidator  ID="PropertyProxyValidator3" runat="server"
             ControlToValidate="txtName" PropertyName="Name"
             SourceTypeName="EntLibStudy.Model.Student,EntlibStudy.Model" ValidationGroup="test"></ cc1:PropertyProxyValidator >
     </ td >
</ tr >
< tr >

具体有关PropertyProxyValidator控件信息可以看下面的第三点分析,这边仅仅是介绍如何应用。

在页面中添加完指定的控件后,还需要在提交的按钮处做一下处理,代码如下:

1
2
3
4
5
6
7
8
protected  void  btnSubmit_Click( object  sender, EventArgs e)
{
     if  (!IsValid)
     {
         return ;
     }
    //具体业务逻辑
}

这步操作是判断页面验证是否通过,如果验证不通过则返回,主要是因为PropertyProxyValidator控件所依赖的验证都在服务器端,需要点击一次提交按钮来进行验证,所以第一次页面的验证是不通过的,需要等到页面上的所有PropertyProxyValidator控件验证通过后页面的验证才会通过。

这时如果未通过验证,服务器端则会通过PropertyProxyValidator控件将验证消息返回给客户端,见下图, 如果全部填写完整则会真正提交页面信息:

pic35

 

虽然企业库的Validation模块为我们提供了这个ASP.NET控件来和Validation进行组合应用,但是我总觉得不友好(最好能使用AJAX验证来提高界面友好性),而且应用面比较窄(可能还有更好的使用方法我没研究出来,如果有哪位朋友有使用经验欢迎分享),使用起来也不怎么方便,建议还是采用ASP.NET原有的验证控件,在数据提交的时候通过后台代码编写进行验证。

我在网上搜索了相关的文章,认为最好的办法就是为Model层的每个子类都统一继承自一个基类,基类里提供统一的验证方法,这样就可以很好的将验证逻辑封装到Model层,表示层只需在获取到数据后调用这个验证方法,验证不通过则将错误消息返回给客户端,具体代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace  EntLibStudy.Helper
{
     [Serializable]
     public  abstract  class  BaseClass<T> where  T : class
     {
         public  string  ValidateTag { get ; protected  set ; }
 
         public  virtual  bool  IsValid()
         {
             var  validateResults = Validation.Validate<T>( this  as  T);
             if  (!validateResults.IsValid)
             {
                 foreach  ( var  item in  validateResults)
                     string .Format( @"{0}:{1}"  + Environment.NewLine, item.Key, item.Message);
                 return  false ;
             }
             return  true ;
         }
     }
}

修改抽象类BaseClass,同时添加一个属性用于存储验证结果,添加一个方法用于实体验证。

界面使用代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
protected  void  btnSubmit_Click( object  sender, EventArgs e)
{
     //if (!IsValid)
     //{
     //    return;
     //}
     BLL.StudentManage studentBll = new  BLL.StudentManage();
     Model.Student student = null ;
     try
     {
         int  studentId = Convert.ToInt32( this .ViewState[ "studentId" ]);
         if  (studentId == 0)
         {
             if  (GetValidatedStudent( ref  student))
             {
                 int  id = studentBll.Add(student);
                 Helper.Utils.MessageBox( this , "新增学员信息成功!" , this .GetRouteUrl( "StudentRoute"
                 {
                     id = id
                 }));
             }
             else
                 Helper.Utils.MessageBox( this , student.ValidateTag);
         }
         else
         {
             student = studentBll.SelectById(studentId);
             if  (GetValidatedStudent( ref  student))
             {
                 studentBll.Update(student);
                 Helper.Utils.MessageBox( this , "编辑学员信息成功!" );
             }
             else
                 Helper.Utils.MessageBox( this , student.ValidateTag);
         }
     }
     catch  (Exception ex)
     {
         throw  ex;
     }
}
/// <summary>
/// 获取已验证的学员对象
/// </summary>
/// <param name="student">学员对象</param>
/// <returns>是否验证成功</returns>
private  bool  GetValidatedStudent( ref  Model.Student student)
{
     if  (student == null )
     {
         student = new  Model.Student();
     }
     student.ClassId = Convert.ToInt32(ddlClass.SelectedValue);
     student.Sid = txtSid.Text.Trim();
     student.Password = txtPwd.Text.Trim();
     student.Name = txtName.Text.Trim();
     student.Sex = Convert.ToInt32(rblSex.SelectedValue);
     student.Birthday = DateTime.Parse(txtBirthday.Text.Trim());
 
     return  student.IsValid();
}

修改了页面的具体代码,添加一个GetValidatedStudent方法用于统一赋值,同时返回实体对象是否验证通过,如不通过则将验证错误消息返回给客户端

 

第三点:简单分析下Validation.Integration.Aspnet实现逻辑

在第二点中已经说过了,Validation.Integration.Aspnet是企业库中Validation模块所提供的一个子模块,其本质是一个ASP.NET控件,核心类就是PropertyProxyValidator.cs,下面我来简单的介绍下这个控件。

PropertyProxyValidator控件其主要作用就是根据配置信息去调用指定的服务器端的验证方法进行验证,如验证不通过则返回验证消息。

类PropertyProxyValidator,继承自ASP.NET中的BaseValidator类,同时实现了接口IValidationIntegrationProxy:

1、BaseValidator类为所有验证控件提供核心实现。验证控件用于验证关联的输入控件中的用户输入。当用户输入的值未通过验证时,验证控件将显示错误信息。由于验证控件是与输入控件分开的,您可以将错误信息定位在页面上相对于输入控件的任意位置。ASP.NET 提供了一些验证控件来执行特定类型的验证。(以上摘自MSDN

由于PropertyProxyValidator继承自BaseValidator类,使得其成为了一个ASP.NET控件(Label控件),基本的客户端验证属性都已经包含在内了。

2、IValidationIntegrationProxy接口是由企业库定义的,其主要作用是为Validation模块提供验证所需行为整合。

在PropertyProxyValidator类中,主要实现了一下方法、属性等:

1、方法BaseValidator.EvaluateIsValid,这个方法的作用是确定输入控件中的值是否有效的代码,其内部实现很简洁,就是创建一个Validator验证器,根据配置通过这个验证器进行验证,然后通过调用内部静态方法FormatErrorMessage来拼装验证返回的消息,最后将这个消息返回给客户端。

PropertyProxyValidator实现的接口IValidationIntegrationProxy主要就为此方法服务,因为创建Validator验证器是通过ValidationIntegrationHelper这个帮助器来创建的,而这个帮助器通过构造函数接收一个实现接口IValidationIntegrationProxy的类,然后帮助器再通过PropertyValidationFactory.GetPropertyValidator属性验证类工厂类中的属性验证器方法调用这个类中所设置好的validatedType(待验证的对象类型)、validatedProperty(待验证的属性信息)、Ruleset(验证规则集)、SpecificationSource(见第5)和ValueAccessBulider(数据访问构造器,这里指向的是类PropertyMappedValidatorValueAccessBuilder)来创建验证器。

2、属性SourceTypeName,待验证对象在服务器端类型,例如:“EntLibStudy.Model.Student,EntLibStudy.Model”,其中逗号前指的是待验证对象所在的类名,逗号后指的是待验证对象所在程序集名。

3、属性PropertyName,待验证对象在服务器端类型中对应的属性名,例如"Name”。

4、属性RulesetName,验证规则集名。

5、属性SpecificationSource,指定的验证信息验证时,调用创建方法所需的源。

6、枚举属性DisplayMode,主要分为3种,List(列表形式)、BulletList(带项目符号的列表形式)和SingleParagraph(段落形式)。

7、事件ValueConvert,用于当控件的值转变时执行验证,对应着委托ValueConverter。

 

以上就是本文的所有内容了,本文主要介绍了企业库的Validation模块中所提供的ASP.NET验证控件。到此企业库的Validation模块就全部介绍完毕了,谢谢大家的浏览。

 

PS:有关在BaseClass中抽象验证参考自:將驗證方法封裝在Model之中(一位台湾的朋友写的)

 

源代码下载:点我下载

 

注意:

1、MSSQL数据库在DataBase目录下(需要自行附加数据库),SQLite数据库在Web目录的App_Data下,由于考虑到项目的大小,所以每个项目的BIN目录都已经删除,如出现无法生成项目请自行添加相关企业库的DLL。

2、由于微软企业库5.0 学习之路这个系列我是准备以一个小型项目的形式介绍企业库的各模块,所以源代码会根据系列文章的更新而更新,所以源代码不能保证与文章中所贴代码相同。

3、项目开发环境为:VS2010+SQL2005。

4、管理员帐户:admin

              密码:admin

 

微软企业库5.0 学习之路系列文章索引:

第一步、基本入门

第二步、使用VS2010+Data Access模块建立多数据库项目

第三步、为项目加上异常处理(采用自定义扩展方式记录到数据库中) 

第四步、使用缓存提高网站的性能(EntLib Caching)

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——上篇

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——中篇 

第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇

第六步、使用Validation模块进行服务器端数据验证

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—上篇

第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇

第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息

第九步、使用PolicyInjection模块进行AOP—PART1——基本使用介绍

第九步、使用PolicyInjection模块进行AOP—PART2——自定义Matching Rule

第九步、使用PolicyInjection模块进行AOP—PART3——内置Call Handler介绍

第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(1)

第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(2)

第十步、使用Unity解耦你的系统—PART3——依赖注入

第十步、使用Unity解耦你的系统—PART4——Unity&PIAB

扩展学习:

扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]

 


本文转自kyo-yo博客园博客,原文链接:http://www.cnblogs.com/kyo-yo/archive/2010/08/04/Learning-EntLib-Sixth-Use-Validation-To-Server-Validate.html,如需转载请自行联系原作者


目录
相关文章
|
11天前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。
|
14天前
|
网络协议 Unix Linux
一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
一个.NET开源、快速、低延迟的异步套接字服务器和客户端库
|
5月前
|
JSON 数据处理 数据安全/隐私保护
Ktor库的高级用法:代理服务器与JSON处理
Ktor库的高级用法:代理服务器与JSON处理
|
25天前
服务器迁移上云训练营打卡学习领好礼
服务器迁移上云训练营打卡学习领好礼
43 4
|
24天前
|
前端开发 Java
学习SpringMVC,建立连接,请求,响应 SpringBoot初学,如何前后端交互(后端版)?最简单的能通过网址访问的后端服务器代码举例
文章介绍了如何使用SpringBoot创建简单的后端服务器来处理HTTP请求,包括建立连接、编写Controller处理请求,并返回响应给前端或网址。
43 0
学习SpringMVC,建立连接,请求,响应 SpringBoot初学,如何前后端交互(后端版)?最简单的能通过网址访问的后端服务器代码举例
|
2月前
服务器迁移上云训练营打卡学习领好礼
服务器迁移上云训练营打卡学习领好礼
37 6
|
3月前
|
存储 缓存 安全
学习服务器硬件基础知识
服务器是指一种高性能计算机,提供计算、存储和通信服务。通常运行在网络环境中,为计算机、设备或用户提供资源共享、数据存储和处理等服务。服务器可以是专门设计的硬件设备,也可以是在普通计算机上运行的特定软件。
75 6
|
4月前
|
存储 运维 Java
函数计算产品使用问题之如何使用Python的requests库向HTTP服务器发送GET请求
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
103 8
|
3月前
|
存储 缓存 Ubuntu
如何在 Apache Web 服务器中安装、配置和使用模块
如何在 Apache Web 服务器中安装、配置和使用模块
78 0
|
4月前
|
网络协议 安全 Python
我们将使用Python的内置库`http.server`来创建一个简单的Web服务器。虽然这个示例相对简单,但我们可以围绕它展开许多讨论,包括HTTP协议、网络编程、异常处理、多线程等。
我们将使用Python的内置库`http.server`来创建一个简单的Web服务器。虽然这个示例相对简单,但我们可以围绕它展开许多讨论,包括HTTP协议、网络编程、异常处理、多线程等。