微软企业库5.0 学习之路——第六步、使用Validation模块进行服务器端数据验证
前端时间花了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类进行了简单的验证:
[StringLengthValidator(, ,
MessageTemplate = "登录ID的长度必须在{3}-{5}之间!")]
//MessageTemplateResourceType = typeof(EntLibStudy.Model.Properties.Resources),
//MessageTemplateResourceName = "SidMessage")]
public string Sid
{
get;
set;
}
[StringLengthValidator(, ,
MessageTemplateResourceType = typeof(EntLibStudy.Model.Properties.Resources),
MessageTemplateResourceName = "PasswordMessage")]
public string Password
{
get;
set;
}
[StringLengthValidator(, ,
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控件,并指定要验证的控件、对应的实体类型及属性名,具体代码如下:
<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控件信息可以看下面的第三点分析,这边仅仅是介绍如何应用。
在页面中添加完指定的控件后,还需要在提交的按钮处做一下处理,代码如下:
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (!IsValid)
{
return;
}
//具体业务逻辑
}
这步操作是判断页面验证是否通过,如果验证不通过则返回,主要是因为PropertyProxyValidator控件所依赖的验 证都在服务器端,需要点击一次提交按钮来进行验证,所以第一次页面的验证是不通过的,需要等到页面上的所有PropertyProxyValidator 控件验证通过后页面的验证才会通过。
这时如果未通过验证,服务器端则会通过PropertyProxyValidator控件将验证消息返回给客户端,见下图, 如果全部填写完整则会真正提交页面信息:
虽然企业库的Validation模块为我们提供了这个ASP.NET控件来和Validation进行组合应用,但是我总觉得不友好(最好能使用AJAX验证来提高界面友好性),而且应用面比较窄(可能还有更好的使用方法我没研究出来,如果有哪位朋友有使用经验欢迎分享),使用起来也不怎么方便,建议还是采用ASP.NET原有的验证控件,在数据提交的时候通过后台代码编写进行验证。
我在网上搜索了相关的文章,认为最好的办法就是为Model层的每个子类都统一继承自一个基类,基类里提供统一的验证方法,这样就可以很好的将验证逻辑封装到Model层,表示层只需在获取到数据后调用这个验证方法,验证不通过则将错误消息返回给客户端,具体代码如下:
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,同时添加一个属性用于存储验证结果,添加一个方法用于实体验证。
界面使用代码如下:
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 == )
{
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 学习之路——第六步、使用Validation模块进行服务器端数据验证的更多相关文章
- 微软企业库5.0 学习之路——第八步、使用Configuration Setting模块等多种方式分类管理企业库配置信息
在介绍完企业库几个常用模块后,我今天要对企业库的配置文件进行处理,缘由是我打开web.config想进行一些配置的时候发现web.config已经变的异常的臃肿(大量的企业库配置信息充斥其中),所以决 ...
- 微软企业库5.0 学习之路——第七步、Cryptographer加密模块简单分析、自定义加密接口及使用—下篇
在上一篇文章中, 我介绍了企业库Cryptographer模块的一些重要类,同时介绍了企业库Cryptographer模块为我们提供的扩展接口,今天我就要根据这些 接口来进行扩展开发,实现2个加密解密 ...
- 微软企业库5.0 学习之路——第四步、使用缓存提高网站的性能(EntLib Caching)
首先先补习下企业库的Caching Application Block的相关知识: 1.四大缓存方式,在Caching Application Block中,主要提供以下四种保存缓存数据的途径,分别是 ...
- 微软企业库5.0 学习之路——第五步、介绍EntLib.Validation模块信息、验证器的实现层级及内置的各种验证器的使用方法——下篇
一.独立验证器 我上篇中我将AndCompositeValidator和OrCompositeValidator归为独立验证器,这2个验证器主要是为了第一类验证服务,可以进行多种验证组合在一起进行复杂 ...
- 微软企业库5.0 学习之路——第十步、使用Unity解耦你的系统—PART2——了解Unity的使用方法(3)
今天继续介绍Unity,在上一篇的文章中,我介绍了使用UnityContainer来注册对象之间的关系.注册已存在的对象之间的关系,同时着重介绍 了Unity内置的各种生命周期管理器的使用方法,今天则 ...
- [EntLib]微软企业库5.0 学习之路——第一步、基本入门
话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白). 直到去年在 ...
- 微软企业库5.0 学习之路——第二步、使用VS2010+Data Access模块建立多数据库项目
现在我就开始进入学习之路的第二步——Data Access模块,这个模块是企业库中被使用频率最高的模块,它很好的封装了数据库操作应用,为我们进行多数据库系统开发提供了便利,只需更改配置文件就 可以很快 ...
- 微软企业库5.0 学习之路——第九步、使用PolicyInjection模块进行AOP—PART4——建立自定义Call Handler实现用户操作日志记录
在前面的Part3中, 我介绍Policy Injection模块中内置的Call Handler的使用方法,今天则继续介绍Call Handler——Custom Call Handler,通过建立 ...
- 微软企业库5.0 学习之路——扩展学习篇、库中的依赖关系注入(重构 Microsoft Enterprise Library)[转]
这篇文章是我在patterns & practices看到的一篇有关EntLib5.0的文章,主要介绍了EntLib5.0的这次的架构变化由来,觉得很不错,大家可以看一下! 在过去几年中,依赖 ...
随机推荐
- 【链表】在O(1)的时间删除链表的节点
/** * 在O(1)的时间删除链表的节点 * * @author * */ public class Solution { public static void deleteNode(Node he ...
- c++ string写时复制
string写时复制:将字符串str1赋值给str2后,除非str1的内容已经被改变,否则str2和str1共享内存.当str1被修改之后,stl才为str2开辟内存空间,并初始化. #include ...
- bzoj [POI2007]旅游景点atr 状态压缩+Dij
[POI2007]旅游景点atr Time Limit: 30 Sec Memory Limit: 357 MBSubmit: 2258 Solved: 595[Submit][Status][D ...
- hive获取日期对应的星期
pmod(datediff(order_date,'2000-01-02'),7)
- CCF-20170901
试题编号: 201709-1 试题名称: 打酱油 时间限制: 1.0s 内存限制: 256.0MB 问题描述 小明带着N元钱去买酱油.酱油10块钱一瓶,商家进行促销,每买3瓶送 ...
- UVA 1635 Irrelevant Elements
https://vjudge.net/problem/UVA-1635 题意:n个数,每相邻两个求和,最后变成1个数,问这个数除m的余数与第几个数无关 n个数使用次数分别为C(n-1,i) i∈[0, ...
- Vue.js -- 过滤器
VueJs中的过滤器基础 过滤器是一个通过输入数据,能够及时对数据进行处理并返回一个数据结果的简单函数.Vue有很多很便利的过滤器,可以参考官方文档, http://cn.vuejs.org/api/ ...
- 【洛谷 P2042】 [NOI2005]维护数列(自闭记第一期)
题目链接 首先,这题我是没A的..太毒瘤了 题目本身不难,都是\(Splay\)的基操,但是细节真的容易挂. 调了好久自闭了,果断放弃.. 希望本节目停更. 放上最终版本 #include <c ...
- Apache的Commons Lang和BeanUtils
1.字符串的空判断 //isEmpty System.out.println(StringUtils.isEmpty(null)); // true System.out.println(S ...
- 工程化管理--maven
mavne模型 可以看出 maven构件都是由插件支撑的 maven的插件位置在:F:\MavenRepository\org\apache\maven\plugins Maven仓库布局 本地仓库 ...