知识大全 服务端数据校验及客户端js脚本验证集成处理初探
Posted 知
篇首语:笔落惊风雨,诗成泣鬼神。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 服务端数据校验及客户端js脚本验证集成处理初探相关的知识,希望对你有一定的参考价值。
这篇文章发出来有段时间了 不过看的人不多 建议的人也少! 今天在首页看到有朋友把验证方案发到首页去了 为了赚些评论我也在这边编辑下发到首页上给大家扔些砖!一 起源
在项目开发中数据有效性验证肯定是必须的 那么在哪里验证呢!?怎么去验证呢? 针对web项目而言 客户端验证+服务端的验证缺一不可 客户端的脚本验证用于提高用户体验! 服务端的验证主要是为了数据的安全性 合法性的验证! 但是我们在实施这两种验证的时候会发现有以下几个可能出现的问题
客户端代码验证写起来相对比较烦琐 而且易出错!(主要是拼写错误 例如js方法名拼写错误)
服务端的验证和客户端验证要保持一致性一样很烦琐 (客户验证输入不能超过 个字符 那后服务器端也要相应的控制在 个字符 而且修改时 需要将客户端和服务端同步修改 提示信息 前后端都要再输入一次!一个字 烦 ) 总觉得时间不应该花在这个上面!
验证与赋值 一般情况下客户端提交的数据 我们验证通过后 把变量的值赋给实体或是相关的变量 如果不通过有些时候我们有时候还会需要给变量或实体属性值加上一个默认值 这个时候我们写的代码可能不避免的出现一些if的判断语句 让代码显得不够简洁
其它的细节问题 这里就不一一列举了 我针对上面的问题 自己做了一个下面的小组件!
二 思路说明
为了解决第一个问题和第二个问题 我决定客户端的验证代码由服务端的验证代码直接生成页面中 这样可以避免客户端的代码在编写上的错误!而服务端的程序代码每次被访问时 通过验证状态开关来开启验证 用户可以根据自己的业务逻辑来开启验证 我先定义了一个验证容器ValidatorContainer和一个验证器Validator两个概念 验证容器是指包括了一个或多个验证器对象的容器类 验证器是针对每一条数据项所添加的验证信息类!
三 调用说明
可能这一部分的内容可以让你更直观的了解这个验证组件的一些原理和信息
第一步 先添加引用 这个不用多说 Validator dll引用进去(最下面附有项目的源码)
第二步 代码都在下面了 不用再说了
cs页面的代码:
using Validator;using My Framework Utility;public partial class _Default : System Web UI Page protected ValidatorContainer vc; protected void Page_Load(object sender EventArgs e) //是否开启服务端验证 bool isStartCheck = false; if (Request[ mand ] == postBack ) /* * 此处的bool值主要控制验证容器处在何种状态 * 状态false 只注册客户端代码不实施服务端的验证 * 状态true 验证客户端的数据并生成客户端代码字符串 * */ isStartCheck = true;
//初始化验证容器的集合 并传入isStartCheck来控制验证的开启 vc = new ValidatorContainer(isStartCheck);
//设置当前的验证组(些处可以根据你自己的页面逻辑来选择验证 不设置为验证所有) vc GroupName = A ;
//获取并验证客户端的数据 int month = vc Add(Validator<int> Init(MyRequest GetInt( monthTextBox )))//注意这一行 我们需要把验证器放置到对应的容器中再进行验证 Integer( 月份必须为 到 的整数 ) Range( 月份必须在 到 月之间 )//验证数字和范围 SetGroupName( A )//设置其所属的验证组 可以不设置(不设置会被分配到default组) RegClientValidator( monthTextBox 请输入出生月 monthErrorSpan )//将验证代码注册到客户端页面(也可以选择不注册) //参数说明 参数 monthTextBox 表示控件的id [参数 ] 请输入出生月 表示提示Div中的文字(该参数为重载) [参数 ] monthErrorSpan 表示错误信息所显示的框(该参数为重载) Retrun( );//返回验证通过后的值 否则返回默认值(此处返回的是 );
string userName = vc Add(Validator<string> Init(MyRequest GetString( userNameTextBox ))) Chinese( 用户名必须为中文! ) Length( 用户名必须在 到 个字以内! ) SetGroupName( A ) RegClientValidator( userNameTextBox ) Retrun( 给你个默认值 );
string rePostDateString = vc Add(Validator<string> Init(MyRequest GetString( rePostDateTextBox ))) Date( 日期格式不正确 ) Range(DateTime Now DateTime MaxValue 重发日期不能少于当前日期! )//这个功能客户端的还没写 SetGroupName( A ) IsRequired(false)//设置其为非必填项 RegClientValidator( rePostDateTextBox 这个是非必填项 当然你如果要填的话 我肯定是要验证的啦! ) Retrun( );
//注册客户端代码到页面中 这里必须要声明运行于服务端的Header或是Form才能进行注册 vc RenderClinetValidator();
//判断验证是否通过 if (isStartCheck) if (vc IsAllPass) //你页面要做的逻辑
aspx页面的调用代码:
<head><! 这里加runat= server 或是如现在的页面有一个 <form id= form runat= server >是runat= server 的 > <title>验证器测试页</title></head><body > <form id= form runat= server > <div> <br /> 请输入出生月份 <input type= text id= monthTextBox value= aa /><span id= monthErrorSpan >这里将用来显示验证反馈信息</span><br /> 请输入用户昵称 <input type= text id= userNameTextBox value= aa /><br /> 更新日期 <input type= text id= rePostDateTextBox value= aa /><br /> <input type= button id= value= 统一验证 onclick= <%=vc Checked( A )%> /><! 上面这个地方就是调用的地方 <%=vc Checked( A )%> 会产生一个js调用函数
A代表要验证的组 产生的这个调用的函数执行完会返回一个表单是否验证通过的bool值 >
</div> </form></body></>
上面这段代码就实现了客户端验证代码的注册及调用 应该来说还是比较简单的!
上面的调用上都写了相关的注释 如果有不明确的地方接着往下看
//是否开启服务端验证 bool isStartCheck = false; if (Request[ mand ] == postBack ) /* * 此处的bool值主要控制验证容器处在何种状态 * 状态false 只注册客户端代码不实施服务端的验证 * 状态true 验证客户端的数据并生成客户端代码字符串 * */ isStartCheck = true;
//初始化验证容器的集合 并传入isStartCheck来控制验证的开启 vc = new ValidatorContainer(isStartCheck);
//设置当前的验证组(些处可以根据你自己的页面逻辑来选择验证 不设置为验证所有) vc GroupName = A ;
上面这段代码里面是初始化开关条件变量以及初始化验证器 以及验证的组名 这个地方组名其实是非必须的 如查不添加这个组名 组件会自动分
配到 Default 组中 在new ValidatorContainer(isStartCheck)中的isStartCheck是用为启动验证的 如果这个值是false的话 那么
ValidatorContainer就只会生成客户端代码而不执行数据有效性验证!
接下来再看下面的代码
//获取并验证客户端的数据 int month = vc Add(Validator<int> Init(MyRequest GetInt( monthTextBox )))//注意这一行 我们需要把验证器放置到对应的容器中再进行验证 Integer( 月份必须为 到 的整数 ) Range( 月份必须在 到 月之间 )//验证数字和范围 SetGroupName( A )//设置其所属的验证组 可以不设置(不设置会被分配到default组) RegClientValidator( monthTextBox 请输入出生月 monthErrorSpan )//将验证代码注册到客户端页面(也可以选择不注册) //参数说明 参数 monthTextBox 表示控件的id [参数 ] 请输入出生月 表示提示Div中的文字(该参数为重载) [参数 ] monthErrorSpan 表示错误信息所显示的框(该参数为重载) Retrun( );//返回验证通过后的值 否则返回默认值(此处返回的是 );
这个里面我们可以看出来 我们用vc Add(Validator<T> v)方法来往验证器里面添加验证器 特别注意的地方是
Validator本身具备了Integer Range 等方法 但是我们这里不可以直接调用 如果直接调用 在这里它的验证结果将不能被vc容监控到!
所以要特别注意
Validator<int> Init(MyRequest GetInt( monthTextBox ))
这小段代码是为MyRequest GetInt( monthTextBox )这个整数做一个校验 这个地方这个方法是另一个组件里的 大家应该看得明白 用
来获取客户端的一个提交值的 如果不为整数的话 默认为 这个地方有点多余 因为验证器里本来就有一个针对整数的验证了 这个我们就先不
管它了 反正我这个组件的思路是不相干的!
后面调用的Integer Range 等方法就不多做解释了 它们只是一个验证方法而已 关键RegClientValidator方法 这个方法有三个重载版本
RegClientValidator(string elementName);这个表示为页面中id或是name为elementName的控件添加js验证的脚本代码 (注:这一步其实只做了一个脚本代码的生成 并没有输出 )
RegClientValidator(string elementName string tipString);这个重载表示 为页面控件添加验证 并在输入时添加提示信息 提示信息的位置现在是
默认的 在控件的上方(具体效果如图 我会在以后的代码更新中会加入一个可以自定义显示的位置 给用灵活的配置或是使用如图的默认)
如果不使用这个重载 自然没有这个提示信息了!
然后讲第三个重载:RegClientValidator(string elementName string tipString string errspanName)
这个重载前两上参数都讲过了 第三个参数其实是控制是否在自定义的元素里面显示错误提示信息
我代码中 monthErrorSpan 其实就是图上红色的那块区域的元素的id 这样如果验证不通过 信息将在红色区域中显示 如果没有使用这个重载
我们会自动生成一个div来显示 效果如下图:
注 这个错误提示的内容就是在cs文件里面写的那些字符串 在哪一下的验证中不通过 就会显示相应的错误提示!
接下来看 Retrurn(T tValue);
这个方法其实就是用来返回值的 意思就是如果验证通过返回用户提交的数据给接收变量 如果不通过将Retrun(T tValue)中定义的值赋给接收变量 这个应该比较好理解 如果你没有定义接收变量 这个方法也可以省略~
然后再看这两个方法
SetGroupName( A ) IsRequired(false)//设置其为非必填项
上面那个SetGroupName( A )表示把该验证添加到A组中 其实这个地方我要声明的是 一般 %甚至更多的页面的验证是不需要分组的 当然这个也用不着 我在这个地方只是为以演示这个分组功能才加上去的 分组验证的情况 有用过的朋友 估计会明白 我这个地方就不多说了 不需要分组的就不用调用这个方法咯!
下面这个IsRequired(false)这个字面上应该也很好理解 就是设置成非必填项 当然如果用户输入了的话 还是会有验证的!
好了 上面对该解释的都解释了 现在看最后的几代码
//注册客户端代码到页面中 这里必须要声明运行于服务端的Header或是Form才能进行注册 vc RenderClinetValidator();
//判断验证是否通过 if (isStartCheck) if (vc IsAllPass) //你页面要做的逻辑 vc RenderClientValidator();这个方法做的工作是客户端验证生成的最后一步 它负责把容器里所有的客户端验证代码生成后写入到代码中~!
有多关键 不用我说了吧!
下面vc IsAllPass这个也不用说了 就是容器里的验证是否都通过了!
差不多了 剩下的代码就是前端的调用 这个地方有些不合理 我估计在下一个更新中会处理掉!
<input type= button id= value= 统一验证 onclick= <%=vc Checked( A )%> />
客户端的代码生成后 在什么地方激活 怎么调用 要看客户的需求了 这个地方需要调用vc Checked(string groupName)来生成js调用代码!
没有这一步的话 程序只会为失去焦点做验证 提交的时候当然就不会做了!
说了蛮多的 不过感觉就是没说清楚!
具体的实现 我挑一两个方法贴出来 更详细的就下载下面的源码吧!最近一直没时间改 这个写了个把月了 一起没有把现在有的问题更新!
不哆嗦了 看代码:
验证器的其中一个验证项方法:
#region 验证数字(int double) /// <summary> /// 验证数字(int double) /// </summary> /// <param name= errorMessage >错误提示字符串</param> /// <returns></returns> public Validator<T> Double(string errorMessage) tempJsonString = new StringBuilder(); tempJsonString Append( Double: ); tempJsonString Append(ConvertToJsonElement( Msg errorMessage)); tempJsonString Append( ); jsonList Add(tempJsonString ToString()); //判断是否需要忽略验证 if (ignore) return this; //验证 if (!IsPattern(validatorRegexs[ ])) this Reject(errorMessage); return this;
#endregion
验证容器的
Codeusing System;using System Collections Generic;using System Text;using Validator;using System Web;using System Web UI;using System Web UI WebControls;using System Security Permissions;
namespace Validator [AspNetHostingPermission(SecurityAction Demand Level = AspNetHostingPermissionLevel Minimal)] public class ValidatorContainer : IObserver /// <summary> /// 是否开启验证 /// </summary> private bool isStartCheck;
/// <summary> /// 验证器所在页对象 /// </summary> private Page cPage;
/// <summary> /// 客户端验证器对象名 /// </summary> private string clientValidatorName;
/// <summary> /// 验证组名 /// </summary> private string groupName;
/// <summary> /// 错误数量 /// </summary> //private int errorCount;
/// <summary> /// 前台呈现脚本代码 /// </summary> private StringBuilder renderString;
/// <summary> /// 验证器列表 /// </summary> private List<ISubject> validatorList;
/// <summary> /// 是否开启验证 /// </summary> public bool IsStartCheck get return isStartCheck; set isStartCheck = value;
/// <summary> /// 客户端验证器对象名 /// </summary> public string ClientValidatorName get return clientValidatorName; set clientValidatorName = value;
/// <summary> /// 验证组名 /// </summary> public string GroupName get return groupName; set groupName = value;
#region 是否通过验证 /// <summary> /// 是否通过验证 /// </summary> public bool IsAllPass get return GetPassStat();
/// <summary> /// 获取验证状态 /// </summary> /// <returns></returns> private bool GetPassStat() foreach (ISubject o in validatorList) if (!o IsPass) return false; return true; #endregion
/// <summary> /// 是否开启验证 /// </summary> /// <param name= _isStartCheck ></param> public ValidatorContainer(bool _isStartCheck) validatorList = new List<ISubject>(); clientValidatorName = Validator ; this isStartCheck = _isStartCheck;
/// <summary> /// 验证器列表 /// </summary> public List<ISubject> ValidatorList get return validatorList; set validatorList = value;
/// <summary> /// 添加字符串验证器 /// </summary> /// <param name= _validator >字符串验证器对象</param> public Validator Validator<string> Add(Validator Validator<string> _validator) if (this groupName != _All ) if (this groupName != _validator GroupName) _validator Ignore = true; validatorList Add(_validator); return _validator;
/// <summary> /// 添加整数验证器 /// </summary> /// <param name= _validator >整数验证器对象</param> public Validator Validator<int> Add(Validator Validator<int> _validator) if (this groupName != _All ) if (this groupName != _validator GroupName) _validator Ignore = true; validatorList Add(_validator); return _validator;
/// <summary> /// 获取所有分组的验证不通过数量 /// </summary> /// <returns></returns> public int GetErrorCount() return ;
/// <summary> /// 获取某分组验证不能过数目 /// </summary> /// <param name= _groupName ></param> /// <returns></returns> public int GetErrorCount(string _groupName) return ;
#region 实现观察者接口 public void GetValidatorStat(ISubject subject) //根据subject中的信息 记录到汇总信息中 //subject GroupName; //subject Ignore; //subject IsPass; //subject ErrorMessage; #endregion
/// <summary> /// 生成客户端验证json代码 /// </summary> /// <returns></returns> public void RenderClinetValidator() RenderClinetValidator(null);
/// <summary> /// 是否存在页面注册区域 /// </summary> /// <returns>存在的区域枚举</returns> private FormOrHeader GetRegisterRegion() cPage = (Page)HttpContext Current Handler; if (cPage Header != null) return FormOrHeader Header; else if (cPage Form != null) return FormOrHeader Form; return FormOrHeader Null;
/// <summary> /// 生成客户端验证json代码 /// </summary> /// <param name= _clientValidatorName >客户端验证器名称</param> /// <returns></returns> public void RenderClinetValidator(string _clientValidatorName) FormOrHeader formOrHeader = GetRegisterRegion(); if (formOrHeader == FormOrHeader Null) throw new Exception( 对不起 页面不存在必须存在标记为\\ runat=server\\ 的Form或是Header标记!请确认! );
//设置客户端验证对象名 if (!string IsNullOrEmpty(_clientValidatorName)) this clientValidatorName = _clientValidatorName;
//按组名排序 validatorList Sort(new GroupComparer());
renderString = new StringBuilder(); renderString AppendLine( <script type= text/javascript > ); renderString AppendLine( var + clientValidatorName + ; ); renderString AppendLine( function InitValidator() ); renderString AppendLine(clientValidatorName + =new MyValidator( + clientValidatorName + Container); ); renderString AppendLine( ); renderString AppendLine( BindEvent(window onload InitValidator); ); renderString AppendLine( var + clientValidatorName + Container= ); int i = ; string currentGroupName; string preGroupName; string nextGroupName; int totalCount = validatorList Count; foreach (ISubject o in validatorList) //设置组名 currentGroupName = validatorList[i] GroupName; preGroupName = validatorList[(i ) < ? : (i )] GroupName; nextGroupName = validatorList[(i + ) > totalCount ? totalCount : (i + )] GroupName; if (i == ) renderString Append(currentGroupName + : ); if (currentGroupName != preGroupName) renderString Append( ); renderString Append( + currentGroupName + : );
i++; renderString Append(o JsonString); if (i != validatorList Count) if (currentGroupName == nextGroupName) renderString Append(o JsonString == string Empty ? : ); renderString Append( ); renderString AppendLine( ; ); renderString AppendLine( </script> );
//加载图片 string imageTemplate = <img id= falseIcon src= style= display:none > ; LiteralControl imageUrlLiterl = new LiteralControl(string Format(imageTemplate cPage ClientScript GetWebResourceUrl(this GetType() Validator Resources icons gif ))); cPage Page Controls AddAt( imageUrlLiterl); //装载样式 string includeTemplate = <link rel= stylesheet text= text/css /> ; string includeLocation = cPage ClientScript GetWebResourceUrl(this GetType() Validator Resources validator css ); LiteralControl includeLocationLiteral = new LiteralControl(String Format(includeTemplate includeLocation)); //装载js string jsTemplate = <script src= type= text/javascript ></script> ; string scriptLocation = cPage ClientScript GetWebResourceUrl(this GetType() Validator Resources MyValidator js ); LiteralControl scriptLocationLiteral = new LiteralControl(String Format(jsTemplate scriptLocation));
if (formOrHeader == FormOrHeader Header) cPage Header Controls Add(includeLocationLiteral); cPage Header Controls Add(scriptLocationLiteral); cPage Header Controls Add(new LiteralControl(renderString ToString())); else cPage Controls AddAt( includeLocationLiteral); cPage Controls AddAt( scriptLocationLiteral); cPage ClientScript RegisterClientScriptBlock(cPage GetType() this clientValidatorName renderString ToString());
/// <summary> /// 验证所有组 /// </summary> /// <returns>组验证调用函数</returns> public string Checked() return Checked( _All );
/// <summary> /// 验证特定组 /// </summary> /// <param name= groupName >组名( _All 表示验证所有组)</param> /// <returns>组验证调用函数</returns> public string Checked(string _groupName) string checkGroup = _All ; if (!string IsNullOrEmpty(_groupName)) checkGroup = _groupName; return clientValidatorName + ValidateByGroup( + checkGroup + ); ;
/// <summary> /// Form或Header /// </summary> public enum FormOrHeader : byte /// <summary> /// 头部 /// </summary> Header /// <summary> /// 表单 /// </summary> Form /// <summary> /// 无 /// </summary> Null
集成在项目中的js的代码我也不贴了 这些js的引用及css的引用 程序都包办了
调用肯定只要引用Validator dll就可以了!
代码质量不高 想到哪写到哪 一直没有时间整理 到时整理出来完善版的再发上来 希望大家给予批评!
真诚的感谢您抽时间来看我的文章!
谢了!
cha138/Article/program/net/201311/13829相关参考
JDBC JavaServlet作为首选的服务器端数据处理技术正在迅速取代CGI脚本Servlet超越CGI的优势之一在于不仅多个请求可以共享公用资源而且还可以在不同用户请求之间保留持续数据本文
如何封装JS和CSS文件为服务器端控件 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 我们以封装
知识大全 Asp.Mvc 2.0用户登录实例讲解:服务器端验证
Asp.Mvc2.0用户登录实例讲解:服务器端验证 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
下面为您介绍的是oracle服务端和客户端之间的网络监听设置如果您在oracle<;服务端和客户端之间的网络监听设置方面遇到过类似的问题不妨一看 oracle服务端和客户端之间的网络监听设
自己编的SQL服务端加客户端 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 自己编的SQL服务端
JavaSocket多线程服务端、客户端 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! //主方
思路用纯JS的方法只能通过判断当前页面的文件名然后算出上下页地址首页和尾页需要在脚本中配置好最后生成导航代码用数据绑定的方法则要简单得多设定dataPageSize然后用firstPage()pr
知识大全 用ICallbackEventHandler实现客户端与服务器端异步
用ICallbackEventHandler实现客户端与服务器端异步 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快
Oracle客户端与数据库应用程序集成安装 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧! 一问题
SVN服务器端与Eclipse中的客户端配置详解 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!