惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
Secure Thoughts
S
Securelist
P
Proofpoint News Feed
D
DataBreaches.Net
Cisco Talos Blog
Cisco Talos Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Project Zero
Project Zero
A
About on SuperTechFans
罗磊的独立博客
WordPress大学
WordPress大学
月光博客
月光博客
Latest news
Latest news
C
Cyber Attacks, Cyber Crime and Cyber Security
GbyAI
GbyAI
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - 三生石上(FineUI控件)
F
Fortinet All Blogs
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
P
Privacy International News Feed
AI
AI
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Stack Overflow Blog
Stack Overflow Blog
M
MIT News - Artificial intelligence
Help Net Security
Help Net Security
T
Tor Project blog
V
Vulnerabilities – Threatpost
C
Cisco Blogs
I
Intezer
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
MyScale Blog
MyScale Blog
雷峰网
雷峰网
MongoDB | Blog
MongoDB | Blog
Forbes - Security
Forbes - Security
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
T
Threat Research - Cisco Blogs
B
Blog RSS Feed
博客园 - 叶小钗
N
News and Events Feed by Topic
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Simon Willison's Weblog
Simon Willison's Weblog
C
CERT Recently Published Vulnerability Notes
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
N
News and Events Feed by Topic

博客园 - KenBlove

错误代码:0x800706BE 解决方法 泛微OA服务器更改IP地址后EMobile出现“调用远端服务器接口时发生错误(122)”的提示 HTTP 错误 404 - 文件或目录未找到 HTTP 错误 401.2 - 未经授权:访问由于服务器配置被拒绝。 优雅还不够,简洁才高效!——用NValidator一句话搞定客户端检测 MyXls初级教程 一个仿PetShop的通用DBHelper类 纯CSS实现底部固定漂浮导航 Access和SQL server开启表间关系,并实现更新或删除母表数据自动更新或删除子表数据 来自微软关于异常处理的17条军规 一个简单的拖动层(兼容IE,FF) SQL Server Profiler过滤本机信息的办法 "The state information is invalid for this page and might be corrupted"错误的一个解决办法 SQL回滚Transaction来调试SQL语句 SQL找出和删除一个表的重复记录 SQL常用判断检测语句 SQL把ID相同的记录合并成同一条记录 关于FireFox记住密码后出现的bug 关于Iframe在IE6下不显示的bug 从丑陋到优雅,让代码越变越美(客户端检测方法思考)
从丑陋到优雅,让代码越变越美续集之服务器端数据校验
KenBlove · 2009-03-31 · via 博客园 - KenBlove

数据校验是两方面的,客户端校验虽然可以大大减少服务器回调次数提升用户体验.但是客户端校验并不是万能的,从原理上说,客户端返回的数据都是不可信任的,服务器端校验必不可少.(关于客户端校验的总结:从丑陋到优雅,让代码越变越美(客户端检测方法思考) )


总的来说,服务器端代码也经历了相似的几个过程:

以判断一个输入是否是可以转换成整数为例,开始大家都会续项强写:

Code1
string str = txtTest.Text;
if (!string.IsNullOrEmpty(str))
{
    
int? intResult = 0;
    
if (int.TryParse(str, out intResult))
    {
        
if(intResult>0 && intResult<100)
        {
            
//success
        }
        
else
        {
            ShowMessage(
"输入必须大于0小于100");
        }
    }
    
else
    {
        ShowMessage(
"不能格式化为Int类型");
    }
}
else
{
    ShowMessage(
"输入为空");
}

看着就够麻烦,然后大家都会总结经验,将检测写成一个一个的函数:

Code2
protected bool IsInt(string str)
{
    
if (!string.IsNullOrEmpty(str))
    {
        
int? intResult = 0;
        
if (int.TryParse(str, out intResult))
        {
            
return true;
        }
    }
return false;
}
protected bool IsInRange(int max,int min,int input)
{
    
if (input > min && input < max)
        
return true;
    
else
        
return false;
}

然后轻松调用:

Code3
if (IsInt(str))
{
    
if(IsInRange(100,0,int.Parse(str))
    {
        
//success
    }
    
else
    {
        ShowMessage(
"输入必须大于0小于100");
    }
}
else
{
    ShowMessage(
"不能格式化为Int类型");
}

这样界面果然清爽多了..但是这样就满足了吗? 当然不是,这样的写法还是有很多缺点的,例如一大堆各种类型的判断函数很难记得住,加的方法多了还很容易重复,还有例如随着判断条件的增多那一堆"If"就让人火大~不优雅啊!!在这个追求优雅的时代,怎么能让这样的代码出在我们追求完美的人的手中? 一定要干掉它们!

下面,我们就介绍一种经过改良的客户端检测解决方案:

Code4
vInfo info = vHelper.StartVerify(txtTest.Text)
    .IsNotNullOrEmpty(
"输入为空")
    .IsInt(
"不能格式化为Int类型")
    .Min(
0"输入小于0")
    .Max(
100"输入大于100")
    .EndVerify();

ShowMessage(info);

上边这个是检测字符串是否只能转换成int并在0到100范围的.下边这个是检测int类型是否属于0到100范围的.

Code5
vInfo info = vHelper.StartVerify(10)
    .IsNotNullOrEmpty(
"输入为空")
    .Min(
0"输入小于0")
    .Max(
100"输入大于100")
    .EndVerify();

ShowMessage(info);

相似吧? 无论在检测的数据是任何类型,都只是同一种写法,浅显易记又优雅(囧!),返回的vInfo是一个贫血的实体类:

Code6
public class vInfo
{
    
private bool _Status;public bool Status
    {
        
get { return _Status; }
        
set { _Status = value; }
    }
private string _Message;public string Message
    {
        
get { return _Message; }
        
set { _Message = value; }
    }
}


返回info是因为我们在后台代码中,往往需要根据检测结果做其他业务方面的处理,如果你不需要返回信息,并不想单独在外边写ShowMessage函数,可以在vInfo里面增加一个ShowMessage函数,让贫血的实体类不在贫血,实现像下面这样看起来更优雅的检测:

Code7
vInfo info = vHelper.StartVerify(10)
    .IsNotNullOrEmpty(
"输入为空")
    .Min(
0"输入小于0")
    .Max(
100"输入大于100")
    .EndVerify()
    .ShowMessage();

当然,不写在实体类,写在我们的检测基类中也可以.不过,ShowMessage的方式往往涉及具体业务逻辑,个人认为还是放到外层比较合适.

废话不说了.先看看我们是如何实现这个检测的,我们先定义个检测基类:

Code8
public class v
{
    
protected bool Status;
    
protected string Message;public vInfo EndVerify()
    {
        vInfo info 
= new vInfo();
        info.Status 
= Status;
        info.Message 
= Message;
        
return info;
    }
}

基类只有一个EndVerify(),这个函数用来返回具体检测结果信息.然后,我们根据各种检测类型构建不同的检测子类.校验不是一个类在战斗,这一刻,校验被工厂模式灵魂附体.....成功了,校验成功了,成功不是靠一个类实现的,他不是一个类....(sorry,扯远了..^_^)

String类型检测子类:

Code9
public class vString:v
{
    
string stringT = null;public vString(string T)
    {
        stringT 
= T;
        Status 
= true;
        Message 
= string.Empty;
    }
public vString IsNotNullOrEmpty(string msg)
    {
        
if (string.IsNullOrEmpty(stringT))
        {
            Status 
= false;
            Message 
= msg;
        }
return this;
    }
public vString IsInt(string msg)
    {
        
if (!Status)
            
return this;int intTemp = 0;
        Status 
= int.TryParse(stringT, out intTemp);
        
if (!Status)
            Message 
= msg;return this;
    }
public vString Min(int min, string msg)
    {
        
if (!Status)
            
return this;if (int.Parse(stringT) < min)
        {
            Status 
= false;
            Message 
= msg;
        }
return this;
    }
public vString Max(int max, string msg)
    {
        
if (!Status)
            
return this;if (int.Parse(stringT) > max)
        {
            Status 
= false;
            Message 
= msg;
        }
return this;
    }
}

int类型检测子类:

Code10
public class vInt:v
{
    
int? intT = null;public vInt(int? T)
    {
        intT 
= T;
        Status 
= true;
        Message 
= string.Empty;
    }
public vInt IsNotNullOrEmpty(string msg)
    {
        
if (intT == null)
        {
            Status 
= false;
            Message 
= msg;
        }
return this;
    }
public vInt Min(int min,string msg)
    {
        
if (!Status)
            
return this;if (intT < min)
        {
            Status 
= false;
            Message 
= msg;
        }
return this;
    }
public vInt Max(int max,string msg)
    {
        
if (!Status)
            
return this;if (intT > max)
        {
            Status 
= false;
            Message 
= msg;
        }
return this;
    }
}

当然..还有更多更多的类在战斗..不过出场机会就是每个类都有.世界是不公平的,总是一部分人先富起来,然后更大部分的人穷下去......Sorry,牢骚了.各位大侠看明白就可以了.废话的看过就算了吧,忘了吧.

最后,万事俱备只欠东风了..粮草兵马都有了,就差一个大将军了,大将军可是调动各个部队的灵魂人物,没有他仗就打不胜利了..下边有请我们的的大将,三军调度员,总设计师,联络官,发言人....(旁白:靠,小样你有完没完啊!!)

Code11
public class vHelper
{
    
int? intT = null;
    
string stringT = null;public static vInt StartVerify(int? T)
    {
        
return new vInt(T);
    }
public static vString StartVerify(string T)
    {
        
return new vString(T);
    }
}

vHelper类就是工厂类,它重载了StartVerify()函数,并根据参数的类型调度不同的检测类来完成检测过程.

怎么样?很简单吧,只要扩展得好,检测不再是难事了吧? 把它们封装到一个dll中吧,这样,你就可以随时随地地校验了.

(当然,没有最好只有更好,小弟在坐井观天呢,您有更好的方法吗?欢迎您指教!另外,对于链式编程,VS2005的智能提示好像有Bug.总不显示提示,不知道VS2008有没有修复.)

最后附上完整代码: 点击下载