Effective C#之Item 39:Use .NET Validation

  rel="File-List" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_filelist.xml"> rel="Edit-Time-Data" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_editdata.mso"> rel="themeData" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_themedata.thmx"> rel="colorSchemeMapping" href="file:///C:%5CDOCUME%7E1%5CHelios%5CLOCALS%7E1%5CTemp%5Cmsohtmlclip1%5C01%5Cclip_colorschememapping.xml">

Item 39: Use .NET Validation

使用.NET验证

User input can come from a variety of locations: You must test input from data files as well as interactive controls. Writing user input validation is pedantic and error-prone but very necessary. Trusting user input can cause anything from exception conditions to SQL injection attacks. None of the options is pleasant. You know enough to be very skeptical of the validity of user input. Good. So does everyone else. That's why the .NET Framework has extensive capabilities that you can use to minimize the amount of code you need to write, yet still validate every piece of data that your users give you.

用户输入会来自很多地方,应该对来自数据文件、交互控件的输入进行测试。编写用户输入验证是呆板的、易出错的,但是很必要。信任用户的输入,可能会引起从异常到SQL注入攻击的任何事情。任何一种情况都不会令人高兴。你要知道很多才对用户输入验证持怀疑态度。好的,其他人也都知道。这就是为什么.Net框架扩展了这方面的能力,你可以利用它减少要写的代码量,并且仍然能验证用户给你的任何数据。

The .NET Framework provides different mechanisms to validate user input for web- and Windows-based applications. Web applications should get data validated at the browser, using JavaScript. The validation controls generate JavaScript in the HTML page. It's more efficient for your users: They do not need to have round-trips back to the server each time they change an entry. These web controls make extensive use of regular expressions to tentatively validate user input before the page is posted back to the server. Even so, you'll want to perform more extensive validation at the server, to prevent programmatic attacks. Windows applications use a different model. User input can be validated in C# code that runs in the same context as the application. The full gamut of Windows controls is available to you when you want to notify the user of invalid input. The general model uses exceptions in property accessors to indicate the invalid input. UI widgets catch those exceptions and display errors to the user.

.Net框架分别为webWindows应用程序提供了不同的机制来验证用户输入。web应用程序应该使用JavaScript来在浏览器上验证数据。验证控件在HTML页面里生成JavaScript代码。对你的用户来说是高效的:在某个输入被改变时,他们不需要在服务器之间传输很多次。这些web控件,在该页面被传回服务器之前,充分利用了正则表达式来暂时验证用户输入。即使这样,你可能希望在服务器上执行更多的验证,用以防范程序性的攻击。Windows应用程序使用不同的模型。用户输入能够在应用程序里用C#代码验证。当你希望通知用户无效输入时,所有Windows控件都是有用的。一般的模型在属性访问符上使用异常处理来指示无效输入。UI窗口将捕获这些异常,将错误显示给用户。

You can use five web controls to handle most of the validation tasks in your ASP.NET applications. All five are controlled by properties that specify the field that should be validated and the conditions for valid input. RequiredFieldValidator forces the user to enter some value in a given field. RangeValidator mandates that a specific field supplies a value within a given range. This range could be the magnitude of a number or the length of a string value. CompareValidator lets you construct validation rules that relate two different fields in a web page. These three are relatively simple. The last two give you all the power you need to validate almost any user input you are expecting. The RegularExpression validator processes the user input using a regular expression. If the comparison returns a match, the user input is valid. Regular expressions are a very powerful language. You should be able to create a regular expression for any situation you have. Visual Studio .NET includes sample validation expressions that help get you started. There is a wealth of resources to help you learn all about regular expressions, and I strongly encourage you to do that. But I can't leave this topic without giving you a few of the most common constructs. Table 5.1 shows the most common regular expression elements you'll use for validating input in your applications.

 

ASP.NET应用程序里面,你能使用5web控件来处理绝大多数的验证任务。5个控件都是由属性来控制这些要验证的特殊的字段。RequiredFieldValidator强制用户在某个特定字段输入一些值。 RangeValidator 要求指定字段的值在某个范围内。该范围可以是某个数值的大小,也可以是一个字符串的长度。CompareValidator让你为web页面上的2个相关的不同字段构建验证规则。这3个相对比较简单。最后2个给你需要的所有能力来验证几乎所有你能想到的用户输入。RegularExpression验证符使用正则表达式来处理用户输入。如果比较的结果是符合,那么该用户输入就是合格的。正则表达式是一个相当有力的语言。你应该有能力为你遇到的任何情况创建一个正则表达式。Visual Studio .NET包含一些验证的例子,可以帮助你开始。这是帮助你学习正则表达式的资源宝库,我强烈的鼓励你进行学习。但是,如果不告诉你一些最常见的结构的话,我就不能继续这个话题。表5.1展示了最通用的正则表达式元素,在你的应用程序验证里面你会用到。

Using these constructs and regular expressions, you will find that you can validate just about anything that your users throw at you. If regular expressions aren't enough for you, you can add your own validator by deriving a new class from CustomValidator. This is quite a bit of work, and I avoid it whenever I can. You write a server validator function using C#, and then you also write a client-side validator function using ECMAscript. I hate writing anything twice. I also avoid writing anything in ECMAscript, so I like to stick to regular expressions.

使用这些结构和正则表达式,你会发现能对用户抛给你的任何东西进行验证。如果正则表达式对你来说还不够的话,你可以从CustomValidator派生新类,以此添加自己的验证对象。这需要一些额外的工作,只要可能,我都尽量的避免这样做。使用C#编写一个服务器验证对象,同时,使用ECMAscript编写一个客户端的验证对象。我痛恨写2次同样的东西。我也尽量避免用ECMAscript编写任何东西,因此我坚持正则表达式。

For example, here is a regular expression that validates U.S. phone numbers. It accepts area codes with or without parentheses around them, as well as any number of whitespace between the area code, exchange, and number. A dash between the area code and the exchange is also optional:

例如,这里有一个正则表达式,用来验证US的电话号码。它接受区号用括号括起来的,或者没有括号的,然后就是区号和号码之间的空格,交换局号,号码。区号和交换局号之间的横线也是可选的:

((/(/s*/d{3}/s*/))|(/d{3}))-?/s*/d{3}/s*-/s*/d{4}

By examining each group of expressions, the logic is clear:

检看每组表达式,逻辑是很清楚的:

((/(/s*/d{3}/s*/))|(/d{3}))-?

This matches the area code. It allows either (xxx) or xxx, where xxx is three digits. Any amount of whitespace surrounding the digits is acceptable. The last two characters, - and ?, allow but do not demand a dash.

这里匹配区号。它允许(xxx) 或者 xxx的格式,只要xxx3个数字就可以。在数字周围有多少空格都是可接受的。最后2个字符,- ?,允许一个横线,但是并不要求。

The remaining portion matches the xxx-xxxx portion of the phone number. /s matches any amount of whitespace. /d{3} matches three digits. /s*-/s* matches a dash surrounded by any number of whitespace. Finally, /d{4} matches exactly four digits.

剩下的部分匹配电话号码的xxx-xxxx部分。/s匹配任何数量的空格。/d{3}匹配3个数字。/s*-/s*匹配任何被空格围绕的横线。最后,/d{4}精确匹配4个数字。

Windows validation works somewhat differently. No precooked validators parse input for you. Instead, you need to write an event handler for the System.Windows.Forms.Control.Validating event. Or, if you are creating your own custom control, override the OnValidating method (see Item 35). A standard form for a validation event handler follows:

Windows应用程序的验证,工作起来有点不一样。你没有预先的验证分析。相反,你需要为System.Windows.Forms.Control.Validating事件编写一个事件句柄。否则,如果你正在创建自己的控件,就要重载OnValidating方法(Item35)。标准的验证事件的格式如下:

  1. private void textBoxName_Validating( object sender,  System.ComponentModel.CancelEventArgs e )
  2. {
  3.   string error = null;
  4.   // Perform your test
  5.   if ( textBoxName.Text.Length == 0 )
  6.   {
  7.     // If the test fails, set the error string
  8.     // and cancel the validation event.
  9.     error = "Please enter a name";
  10.     e.Cancel = true;
  11.   }
  12.   // Update the state of an error provider with
  13.   // the correct error text. Set to null for no
  14.   // error.
  15.   this.errorProviderAll.SetError( textBoxName, error );
  16. }
 

You have a few more small tasks to make sure that no invalid input sneaks through. Every control contains a CausesValidation property. This property determines whether the control participates in validation. In general, you should leave it true for all of your controls, except for the Cancel button. If you forget, the user must create valid input to cancel from your dialog box. The second small task is to add an OK handler to force validation of all controls. Validation happens only when a user visits and leaves a control. If the user opens a form and immediately presses OK, none of your validation code executes. To fix that, you add an OK button handler to walk through all your controls and force them to validate. The following two routines show you how to do this correctly. The recursive routines handle those controls that are also containers for other controls: tab pages, group boxes, and panels:

你有一些小小的工作要做,来确认不会漏掉任何无效输入。每个控件都包含一个CausesValidation属性。该属性决定该控件是否参与验证。一般来讲,你所有的控件都应将它设置为true,除了Cancel按钮。如果你忘记的话,用户就必须创建有效的输入,来取消对话框。第二个小任务就是,添加一个OK处理者,强制所有的控件都参与验证。只用当用户访问或者离开一个控件的时候才发生。如果一个用户打开了一个窗体并且迅速的点击了OK,那么,你的任何验证代码都不会被执行。为了修正这个错误,需要向所有的控件添加一个OK事件处理者,强制他们进行验证。接下来的两段小代码向你展示了如何正确的做。循环子程序处理那些同时也作为其他控件容器的控件:tab pages, group boxes, and panels:

  1. private void buttonOK_Click( object sender,  System.EventArgs e )
  2. {
  3.   // Validate everyone:
  4.   // Here, this.DialogResult will be set to
  5.   // DialogResult.OK
  6.   ValidateAllChildren( this );
  7. }
  8.  
  9. private void ValidateAllChildren( Control parent )
  10. {
  11.   // If validation already failed, stop checking.
  12.   ifthis.DialogResult == DialogResult.None )
  13.     return;
  14.  
  15.   // For every control
  16.   foreach( Control c in parent.Controls )
  17.   {
  18.     // Give it focus
  19.     c.Focus( );
  20.  
  21.     // Try and validate:
  22.     if (!this.Validate( ))
  23.     {
  24.       // when invalid, don't let the dialog close:
  25.       this.DialogResult = DialogResult.None;
  26.       return;
  27.     }
  28.     // Validate children
  29.     ValidateAllChildren( c );
  30.   }
  31. }
  32.  

This code handles most normal cases. A special shortcut applies to the DataGrid/DataSet combination. Assign the ErrorProvider's DataSource and DataMember properties at design time:

这些代码处理了几乎所有的一般情况。一个特殊的快捷应用就是DataGrid/DataSet的组合。在设计时指定ErrorProviderDataSource以及DataMember属性:

  1. ErrProvider.DataSource = myDataSet;
  2. ErrProvider.DataMember = "Table1";
Or, at runtime, call the BindToDataAndErrors method to set both in one operation:

或者,就在运行时,调用BindToDataAndErrors方法来在一个操作里面同时对他们进行设置。

  1. ErrProvider.BindToDataAndErrors(  myDataSet, "Table1" );
      Errors get displayed by setting the DataRow.RowError property and calling the DataRow.SetColumnError method to display specific errors. The ErrorProvider displays the red exclamation icon on the row and the specific cell in the DataGrid.

通过设置DataRow.RowError 属性可以显示错误,调用DataRow.SetColumnError 方法可以显示指定的错误。ErrorProvider 会在DataGrid的原始的行上的指定单元格里显示红色的警告图标。

This whirlwind tour of the validation controls in the framework should help you efficiently create the validation you need in many applications. User input cannot be trusted: Users make mistakes, and occasionally malicious users try to break your application. By making the most use of the services already provided by the .NET Framework, you reduce the code you need to write. Validate all user input, but do it efficiently with the tools already provided.

大概的了解.net框架里的验证控件,在很多应用程序中,可能对你创建所须要的高效验证很有帮助。用户的输入不能完全信任:用户会出现错误,而且有时会有一些恶意的用户试图破坏你的应用程序。通过充分利用.Net框架已经提供的服务,可以减少自己的代码编写工作。验证所有用户的输入,但要使用已经提供了的高效工具。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值