Asp.net表单自动验证

引入

          对于表单密集型的页面(比如注册页面等),内容合法性验证往往是一件比较繁琐的事情。比如对于下面的例子:

image

按照我以往的做法,我会在后台处理方法中这么做:

image

或许可以将 if() 中的判断提取出为一个通用的验证方法,但对于本文所讨论的自动验证来说还远远不够,因为你还是需要写很多的if…else来判断合法性,这些重复的操作在我看来是一件非常丑陋的事情。

我理想中的自动验证应该是这个样子的:在需要验证的地方简单的调用一句话就能完成所有控件的合法性验证操作,比如说像下面这样:

image

不管实现的方式如何,我觉得我们的设计就应该围绕这个思想来进行。即先把实现的最终方式定下来,然后想法设法的根据这种最终实现来完成中间的步骤。我觉得这样可以明确我们的目标,又可以使得验证按照我们想象的那样进行工作。

实现

           现在我们顺着上面的思路进行设计。首先,我们可以根据上面理想中的验证方式提出几个问题出来:

1. 程序如何知道哪些控件是需要验证,而哪些控件是不要进行验证的

2. 具体验证控件的时候,又如何确定是按什么验证类型来进行验证。比如到底对这个控件是不能为空呢,还是必须是Email类型格式…

这两个问题差不多可以用同一个方法来解决。就是给控件加上一个【Validate】属性,这个属性的值就是你要指定的给这个控件的验证类型,像这样:

image

这里需要注意的是这个【Validate】属性并不是TextBox自带的,所有在书写的时候并没有自动提示(不管怎样我们还是这样写上去了)。有了这个属性我们就很自然的想如果能在后台处理的时候得到这个属性值那么每个控件就知道如何去验证了。不幸的是控件根本就不认得这个Validate属性,因为它不是内置的。如下图所示:

image

于是,新的挑战来了。如何在后台得到我们“手动”给每个控件附加的Validate属性呢?联想到ViewState的实现方法,或许我们可以这样做:

1. 写一个服务端控件,并将其放到需要验证的页面中的某个地方。然后在Render方法中循环该服务端控件所在的页面的所有控件,并将每个控件的Id写入到一个隐藏域中。如下图所示:

image

这样,你在前台就会看到如下图所示的许多的隐藏域。

image

2. 通过一段JS代码,我们可以将所有带有Validate属性的input填充到对应的隐藏域中。

image

拿本例来说,就会将tbUser的validate值”NotNull”填充到name为tbUser_Validate_的隐藏域当中。通过这种方法我们就有机会通过隐藏域的方式在后台得到每个需要验证的控件的Validate属性值了。

3. 在上面的Validate验证方法中我们就可以这样做:

image

也就是对于每个控件,他会尝试去取得特定格式的隐藏域,如果取到了则说明该控件被标记为需要验证。然后通过隐藏域取出验证规则(服务端设定的Validate的值)并进行验证。

分析到这边这个程序的核心思想就算说完了。当然,为了它更加易用,我还做了如下一些动作。

1. 将这个服务端控件继承自Panel控件。

image

这样做的好处就是给验证带来了【区域】的概念。在同一个页面,使用者能够根据服务端控件所包围的区域的不同从而区别验证。例如:

image

我只想在某些情况下验证几个属性,那么就可以将这些属性包围在一个服务端控件中(有点类似于panel的用法吧)。这样在需要的地方直接调用

image

就可以完成secondValidate包围区域里面的控件的验证了。

2. 当验证失败时,为了让使用者知道到底是哪个控件出现了何种验证错误我还涉及了一个InValidateInfo类用于提供错误信息。该类的被作为一个成员变量放在我们设计的服务端控件中。

image

这样当验证出错时,我们可以通过以下的用法来获得具体的验证错误信息,以便处理信息。

image

3. 提供了客户端验证功能。

好的验证不应该得等到服务端才去验证错误。如果能够在客户端就及时通知用户哪里输入不对不是更好吗?!类似于前面所讲思想,我还设计了一个客户端验证JS方法:ClientFormValidate(formValidateId,ErrorInfo),ErrorInfo用于提供错误信息。

image

这样在你需要的地方可以调用这个方法来达到客户端验证的目的。当然,我们只提供验证错误信息,至于如果处理完全有使用者自己决定。

不足

           世界上没有完美的事物,本文设计的这个东东当然也有许多不完美的地方。限于我的能力、时间有限,我只能做到这里。下面我觉得比较遗憾的地方:

1. Vlidate中的验证规则在书写的时候没有自动提示,如果能像枚举类型那样显示出本框架支持的验证方式就好了。而现在使用者只能查阅说明去写字符串了。

image

为什么不能支持?因为在服务端控件里面写<%=%>是不被识别的,而写<%# %>有需要绑定才能够使用。

2. 对于第三方的控件支持不好。关键就在循环的时候判断控件类型的时候被限制住了。

image

所以他可能不会认得第三方控件(虽然我们可以扩展所有的ASP.Net自己的控件,但也是个遗憾)。我想到的一个解决方法是使用反射,反射该控件是否具有Text属性。但那样的话性能不是很好,而且也不能覆盖所有的情况,所以我也就没有实施。

3. 该控件依赖于Jquery。当然这个可以解决,如果我的javascript足够好的话…..

下载

https://files.cnblogs.com/qianlifeng/AutoValidate.zip

http://code.google.com/p/autovalidate/

原文地址:https://www.cnblogs.com/qianlifeng/p/2212252.html