演练:验证 Web 窗体页中的用户输入
更新:2007 年 11 月
本演练阐释如何使用 ASP.NET 验证程序控件检查网页中的用户输入。您无需代码就可以使用某些自动执行所有检查的控件。此外,您还将通过编写代码创建一个自定义验证程序,该过程将演示如何将您自己的逻辑添加到页的验证框架中。最后,您将学习如何根据用户在页上所做的选择有条件地验证用户输入。
在本演练中,您将为网站创建一个允许访问者申请预订的页面。由于本演练的目的是为阐释验证,因此预订什么对本演练并不重要(例如,可预订餐厅、社区中心会议室或别的地点),并且该页并不真正处理预订。
您所创建的该页将提示用户输入电子邮件地址、预订人数和预订日期。该页还允许用户申请其预订的电话确认。(如果该页实现该功能,则该功能默认为电子邮件确认。)
安全说明: |
---|
默认情况下,Web 窗体页将自动验证是否有恶意用户试图将脚本发送到您的应用程序中。有关更多信息,请参见脚本侵入概述。 |
通过此演练,您将学会如何执行以下任务:
使用验证程序控件检查 ASP.NET 网页中的用户输入。
设置显示验证错误消息的格式。
通过编写代码创建自定义验证。
先决条件
若要完成本演练,您需要:
- Visual Studio 和 .NET Framework。
创建网站和网页
在本演练的第一部分,将创建可以使用样式的网站和网页。
如果您已在 Visual Studio 中创建了一个网站(例如,通过主题演练:在 Visual Web Developer 中创建基本网页),则可以使用该网站并跳到本演练后面的“添加控件”部分。否则,按照下面的步骤创建一个新的网站和网页。
创建文件系统网站
打开 Visual Studio。
在“文件”菜单上单击“新建网站”。
“新建网站”对话框随即出现。
在“语言”列表中,单击您想使用的编程语言。
您选择的编程语言将是网站的默认语言,但您可以为每个页面分别设置编程语言。
在“Visual Studio 已安装的模板”之下单击“ASP.NET 网站”。
在“位置”框中输入要保存网站页面的文件夹的名称。
例如,键入文件夹名“C:\WebSites”。
单击“确定”。
Visual Studio 创建该文件夹和一个名为 Default.aspx 的新页。
添加控件
您将只使用几个控件提示用户输入预订所需的信息。
添加控件和文本
切换到“设计”视图。
键入一个页标题,如“Submit a Reservation”(提交预订)。
从“工具箱”的“标准”组中,将下列控件拖到该页上并按指示设置其属性。
控件
属性
ID:“textEmail”
ID:“textNumberInParty”
ID:“textPreferredDate”
ID:“buttonSubmit”
Text:“Submit Request”(提交申请)
ValidationGroup:“AllValidators”
ID:“labelMessage”
Text:(空白)
说明: 页的具体布局无关紧要。
在上述这些文本框之前键入文本作为标题。
双击 Submit Request 按钮以为其 Click 事件创建一个处理程序,然后添加以下突出显示的代码:
Protected Sub buttonSubmit_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) If Page.IsValid Then labelMessage.Text = "Your reservation has been processed." End If End Sub
protected void buttonSubmit_Click(object sender, EventArgs e) { if (Page.IsValid) { labelMessage.Text = "Your reservation has been processed."; } }
该按钮处理程序只显示一条消息;它不执行实际的处理操作。但显示该消息将允许您在本演练的后面部分测试验证结果。
切换到“设计”视图,双击该页上的空白区域以创建一个 Page_Load 处理程序,然后添加以下突出显示的代码:
Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As EventArgs) labelMessage.Text = "" End Sub
protected void Page_Load(object sender, EventArgs e) { labelMessage.Text = ""; }
在通过所有验证后,该代码将清除该页上所显示的消息。该代码对本演练后面部分的测试很有用。
添加基本验证
对于您虚构的预订系统,您将希望执行下列验证检查:
必须填写电子邮件地址,并且该项的格式设置必须正确;例如,someone@example.com。(通常不可能检查某一电子邮件地址是否是某人的真实地址,但可以检查该地址是否符合电子邮件地址的正确格式。)
必须填写人数,并且该项必须是数字。
必须填写预订日期。
可以使用验证程序控件添加所有这些验证,这些控件将为您执行所有检查并自动显示错误。
说明: |
---|
在本演练后面部分,您将添加另一项检查以确定用户是否输入了有效日期。 |
添加基本验证
切换到“设计”视图。从“工具箱”的“验证”组中,拖动一个 RequiredFieldValidator 控件并将该控件放在 textEmail 文本框旁边。
设置 RequiredFieldValidator 控件的以下属性:
属性
设置
textEmail
将该验证程序控件绑定到要验证其内容的文本框。
Dynamic
指定只在显示错误需要时才呈现该控件(并且该控件占用页面上的空间)。
必须填写电子邮件地址。
显示摘要错误中的文本,将在本演练后面部分配置该属性。
*
星号是指示某字段必填的简便方法。只在出现错误时,才显示该文本。
AllValidators
与单选按钮一样,可以将验证程序分组成视为单元的各个组。您将在本演练后面部分学习有关对验证程序进行分组的更多内容。
您现在已完成的任务是添加一个测试以确定用户是否输入了电子邮件地址。该验证程序控件将执行所有检查并在需要时显示错误,这需要您向该页添加代码。
从“工具箱”的“验证”组中,拖动一个 RegularExpressionValidator 控件并将该控件放在刚添加的 RequiredFieldValidator 旁边。
设置 RegularExpressionValidator 控件的以下属性:
属性
设置
textEmail
您要再次对电子邮件框中的用户输入进行验证。
Dynamic
电子邮件地址必须采用 name@domain.xyz 格式。
一个较长的错误消息。
无效格式!
一个较短的错误消息。
AllValidators
与单选按钮一样,可以将验证程序分组成视为单元的各个组。您将在本演练后面部分学习有关对验证程序进行分组的更多内容。
在 RegularExpressionValidator 控件仍处于选定状态时,在“属性”窗口中单击 ValidationExpression 框中的省略号按钮。
正则表达式构成了可用于在字符串中查找精确定义格式的语言。在 RegularExpressionValidator 控件中,为有效格式定义一个正则表达式;在本例中,是有效电子邮件地址的格式。
“正则表达式编辑器”包含一个常用正则表达式列表,这样您无需了解正则表达式语法就可以使用验证程序控件。
在“标准表达式”列表中,单击“Internet 电子邮件地址”。
电子邮件地址的正则表达式随即将放入“验证表达式”框中。
单击“确定”关闭对话框。
按照步骤 1 至 3 中的说明添加另一个 RequiredFieldValidator 控件。但这一次将该控件绑定到 textNumberInParty 文本框并将其 ErrorMessage 属性设置为“Please indicate how many people are in your party”(请指出团队人数)。
从“工具箱”的“验证”组中,拖动一个 RangeValidator 控件并将该控件放在刚添加的 RequiredFieldValidator 旁边。
设置 RangeValidator 控件的以下属性:
属性
设置
textNumberInParty
Dynamic
为团队人数输入一个介于 1 和 20 之间的数字。
20
在本例中,为任意较大的值。
1
在此申请中,至少需要预订一人。
输入一个介于 1 和 20 之间的数字。
Integer
AllValidators
RangeValidator 控件执行下面两个功能:首先确保用户所输入的数据是数字,然后检查该数字是否在指定的最小值和最大值之间。
测试该页
现在可以测试到目前为止所创建的验证程序控件。
测试基本验证
按 Ctrl+F5 运行该页。
当在浏览器中显示该页时,单击 Submit Request 按钮。
由于您尚未填写某些必填字段,因此显示了几个验证错误。您会立即看到这些验证错误,并且未能提交该页。默认情况下,验证程序控件将客户端 ECMAScript (JavaScript) 插入该页中以在浏览器中执行验证检查。这为用户提供了有关验证错误的即时反馈;在不使用客户端脚本的情况下,对验证错误的检查将需要执行一个到服务器的往返过程,该过程有时可能会很慢。实际上,直到所有客户端验证检查都通过后,才能提交该页。(在提交该页时,作为一项安全预防措施将再次执行相同的验证检查。)
检查对 textEmail 文本框的验证,方法是键入一个无效的电子邮件地址,然后再输入一个有效的电子邮件地址(如您自己的地址)。
检查是否只能在“Number of people in party”(团队人数)文本框中输入介于 1 和 20 之间的数值。
在输入有效值后,单击“Submit Request”(提交申请)按钮。如果所有控件都通过了验证,您将会看到消息“Your reservation has been processed”(您的预订已得到处理)。
在确认验证正常工作后,关闭浏览器。
如果验证未正常工作,则复查上面列出的所有属性设置,然后再次运行该页。
显示错误信息的其他方法
默认情况下,验证程序控件就地显示错误文本;也就是说,这些控件在其所在页上的位置显示其 Text 属性值。有时,您可能希望用不同的方法显示错误信息。ASP.NET 验证程序控件为您提供了这些附加选项:
将所有验证错误汇总在一个位置。可以另外执行此选项或用此选项代替就地显示错误。显示错误摘要还使您可以显示较长的错误消息。
在浏览器中显示一个包含错误信息的弹出消息。该选项只适用于启用脚本的浏览器。
可以使用 ValidationSummary 控件添加这两个显示选项。在本部分演练中,您将为该页添加这两个显示功能。
用其他方法显示验证信息
从工具箱的“验证”组中,将 ValidationSummary 控件拖动到页面上。
将 ValidationSummary 控件的 ValidationGroup 属性设置为 AllValidators。
运行该页。
执行您在演练的前面部分所执行的相同测试。
对于每条错误,您将看到在两个位置中显示了错误信息。在验证程序控件所在的位置上显示了一条简短的错误消息(验证程序的 Text 属性值)。在 ValidationSummary 控件中显示了一条较长的错误消息(该控件的 ErrorMessage 属性值)。
关闭浏览器。
将 ValidationSummary 控件的 ShowMessageBox 属性设置为 true。
运行该页。
执行相同的测试。
此时,每条错误将会导致在浏览器中显示一个弹出消息。
关闭浏览器。
添加用于检查日期输入的自定义验证
ASP.NET 验证控件不包含自动检查有效日期的控件。但可以将 CustomValidator 控件用于此用途。自定义验证程序控件使您可以编写自己的验证代码来检查应用程序所需的任何条件。在本演练中,您将使用 CustomValidator 检查用户在 textPreferredDate 文本框中输入的值是否可以转换为日期值。
您将添加两个自定义验证代码块。第一个代码块是在提交该页时运行的自定义验证代码。必须始终具有 CustomValidator 控件的服务器端验证逻辑。还必须编写在浏览器中执行类似检查的某一客户端脚本(ECMAScript 或 JavaScript),以便用户可以获得即时反馈。
使用 CustomValidator 控件检查有效日期
从“工具箱”的“验证”组中,将一个 CustomValidator 控件拖到该页上并将该控件放在 textPreferredDate 文本框旁边。
设置 CustomValidator 控件的以下属性:
属性
设置
textPreferredDate
Dynamic
以 m/d/yyyy 格式输入一个日期。
无效日期格式(需要 m/d/yyyy)。
AllValidators
双击 CustomValidator 控件以为其 ServerValidate 事件创建一个处理程序,然后添加以下突出显示的代码:
Protected Sub CustomValidator1_ServerValidate( _ ByVal source As Object, _ ByVal args As System.Web.UI.WebControls.ServerValidateEventArgs) Try DateTime.ParseExact(args.Value, "d", _ System.Globalization.DateTimeFormatInfo.InvariantInfo) args.IsValid = True Catch args.IsValid = False End Try End Sub
protected void CustomValidator1_ServerValidate(object source, ServerValidateEventArgs args) { try { DateTime.ParseExact(args.Value, "d", System.Globalization.DateTimeFormatInfo.InvariantInfo); args.IsValid = true; } catch { args.IsValid = false; } }
在用户提交该页时运行该代码。该代码使用传入处理程序的 ServerValidateEventArgs (args) 对象与该验证程序控件交互。用户在 textPreferredDate 文本框中所输入的值作为 args 对象的 Value 属性传递。在检查用户输入是否有效后,将 args 对象的 IsValid 属性相应地设置为 true 或 false。如果将该属性设置为 false,则该验证程序将显示其错误消息。
在本示例中,该代码使用 try-catch 块确定用户输入是否可以转换为 DateTime 对象。如果用户输入一个无效值(不符合 m/d/yyyy 日期格式的任何值),则 DateTime 对象的 ParseExact 方法会引发一个异常,并执行 Catch 块。
说明: DateTime.ParseExact 方法的 provider 参数的值与区域性无关。如果需要使用当前区域性,可以将 provider 设置为 null。
在 Button_Click 处理程序中,添加以下突出显示的代码:
Protected Sub buttonSubmit_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) If Page.IsValid Then labelMessage.Text = "Your reservation has been processed." Else labelMessage.Text = "Page is not valid."End If End Sub
protected void buttonSubmit_Click(object sender, EventArgs e) { if(Page.IsValid) { labelMessage.Text = "Your reservation has been processed."; } else { labelMessage.Text = "Page is not valid."; } }
在使用 CustomValidator 控件时,必须在任何服务器端处理期间检查 Page.IsValid 属性以确定是否通过了所有验证检查。IsValid 属性返回该页上所有验证程序控件的累积状态。此属性用于确保任何服务器端处理都已通过所有验证检查。
现在您已为 CustomValidator 控件添加了用于检查有效日期的服务器端代码。正如您在本演练前面部分所了解的那样,验证程序控件还使用客户端脚本检查用户输入。也可以将客户端脚本添加到 CustomValidator 控件中。实际上,就是编写重复服务器端验证所执行的逻辑的客户端脚本。编写客户端自定义验证代码并不总是可行(例如,如果自定义代码通过查找服务器端数据库验证用户输入)。但在本例中可以创建客户端代码,该代码执行的检查基本上与服务器端代码所执行的检查相同。
向 CustomValidator 控件添加客户端脚本
打开或切换到 Default.aspx。
在该页的 <head> 元素中,添加以下客户端脚本块:
<script language="javascript"> function validateDate(oSrc, args) { var iDay, iMonth, iYear; var arrValues; arrValues = args.Value.split("/"); iMonth = arrValues[0]; iDay = arrValues[1]; iYear = arrValues[2]; var testDate = new Date(iYear, iMonth - 1, iDay); if ((testDate.getDate() != iDay) || (testDate.getMonth() != iMonth - 1) || (testDate.getFullYear() != iYear)) { args.IsValid = false; return; } return true; }</script>
说明: ECMAScript (JavaScript) 区分大小写;因此应完全按原样输入该代码。
该代码类似于服务器端验证检查,但不完全相同。将用户输入作为 args 对象的 Value 属性传入该函数,并且可以设置该对象的 IsValid 属性以指示该值是否通过验证。在本示例中,该代码检查所输入的数值日期是否有效。
请注意,用于自定义验证的代码在客户端脚本中与在服务器代码中略有不同。ECMAScript 所提供的功能与 .NET Framework 中所提供的功能不完全相同。因此,ECMAScript 分析输入的文本,而不是服务器上用于检查日期的 ParseExact 代码。但这两种验证检查(客户端和服务器)的相似性足以提供您所需的功能。
将插入点放在 <asp:customvalidator> 元素中以选中它。
在“属性”窗口中,将该控件的 ClientValidationFunction 属性设置为 validateDate,这是刚创建的 ECMAScript 函数的名称。
现在您已添加了一个在客户端脚本中使用的自定义验证检查,用于立即检查用户输入,并在将该页提交给服务器时再次检查用户输入。
测试自定义验证
您现在可以测试该自定义验证是否正常工作。
测试自定义验证
通过将 CustomValidator 控件的 EnableClientScript 属性设置为 false,暂时禁用客户端验证。
按 Ctrl+F5 运行该页。
填写电子邮件地址和团队人数,以便通过对这些字段的验证。
在日期文本框中,输入一个显然不是日期的字符串,然后单击 Submit Request 按钮。
该页将执行一个到 Web 服务器的往返过程,在此期间服务端验证将失败。对 IsValid 的测试也将失败,并且 labelMessage 将显示“该页无效”。
填写有效日期值(如 11/17/2005)并单击该按钮。
这次,该日期值通过了验证,因此您会看到在该按钮的 Click 处理程序中创建的确认消息。
关闭浏览器。
通过将 CustomValidator 控件的 EnableClientScript 属性重新设置为 true,重新启用客户端验证。
再次运行该页并输入有效的电子邮件地址和团队人数。
在日期文本框中输入一个无效日期值,然后按 Tab 键。(不要单击该按钮。)
在日期文本框失去焦点时,客户端验证脚本就会立即运行,并且您会看到一条错误消息。
说明: 如果在 Internet Explorer 中使用的是自动完成选项,则从自动完成列表中选择某一值时将会向文本框添加该值,但客户端验证程序不会运行。
单击 Submit Request 按钮。
由于对日期文本框的客户端验证已失败,因此不提交该页。
纠正日期值并再次按 Tab 键。
错误消息将消失。现在可以提交该窗体。
添加带有条件验证的可选控件
在本演练的最后一部分中,您将向预订表单添加某些可选信息。用户可以选中一个框以指示他们希望通过电话确认预订。如果用户这样做,他们必须输入其电话号码。因此,该页将包含另两个控件:一个复选框和一个文本框。
与前面一样,您将使用验证检查用户输入。您将使用一个 RequiredFieldValidator 控件来确定用户是否输入了电话号码,并使用一个 RegularExpressionValidator 控件检查其格式。电话号码是可选的;只有在用户选中 Confirm reservation by phone 复选框时才需要检查电话号码。因此,您将编写一些简单代码,用于根据复选框的状态打开或关闭对电话号码的验证。
添加条件验证
从“工具箱”的“标准”组中,将一个 CheckBox 控件拖到该页上并设置下列属性:
属性
设置
checkPhoneConfirmation
True
在用户单击复选框时,该页将执行一个往返过程并有条件地启用其相应文本框和对该文本框的验证。
False
单击 CheckBox 将不会自动执行验证。
通过电话确认预订。
将一个 TextBox 控件拖到该页上的 CheckBox 控件下并设置下列属性:
属性
设置
textPhoneNumber
False
直到用户单击复选框之后,才会启用其相应文本框。
在电话号码文本框的旁边键入类似于“Telephone number:”(电话号码:)这样的文本作为标题。
从“工具箱”的“验证”组中,将一个 RequiredFieldValidator 拖到该页上并设置下列属性:
属性
设置
validatorRequiredPhoneNumber
在本演练前面部分未设置验证程序控件的 ID,但在本例中将在代码中引用验证程序控件,因此为该控件指定助记 ID 是十分有用的。
textPhoneNumber
Dynamic
必须提供一个电话号码。
*
(保留为空白)
如果该属性为空,则该验证程序不属于为页上其他验证程序控件创建的 AllValidators 组。因此,在单击 buttonSubmit 控件时默认情况下不检查此验证程序。
将一个 RegularExpressionValidator 控件拖到该页上并设置下列属性:
属性
设置
validatorRegExPhoneNumber
textPhoneNumber
Dynamic
电话号码格式无效
无效格式
(使用“正则表达式编辑器”对话框选择“美国电话号码”或其他电话号码表达式。)
(保留为空白)
双击 checkPhoneConfirmation 控件以为其 CheckedChanged 事件创建一个处理程序,然后添加以下突出显示的代码:
Protected Sub checkPhoneConfirmation_CheckedChanged( _ ByVal sender As Object, _ ByVal e As System.EventArgs) If checkPhoneConfirmation.Checked = True Then textPhoneNumber.Enabled = True validatorRequiredPhoneNumber.ValidationGroup = "AllValidators" validatorRegExPhoneNumber.ValidationGroup = "AllValidators" Else textPhoneNumber.Enabled = False validatorRequiredPhoneNumber.ValidationGroup = "" validatorRegExPhoneNumber.ValidationGroup = "" End If End Sub
protected void checkPhoneConfirmation_CheckedChanged( object sender, EventArgs e) { if(checkPhoneConfirmation.Checked) { textPhoneNumber.Enabled = true; validatorRequiredPhoneNumber.ValidationGroup = "AllValidators"; validatorRegExPhoneNumber.ValidationGroup = "AllValidators"; } else { textPhoneNumber.Enabled = false; validatorRequiredPhoneNumber.ValidationGroup = ""; validatorRegExPhoneNumber.ValidationGroup = ""; } }
当用户单击复选框时,与其相应文本框相关联的两个验证程序将添加到包含其他验证程序控件的验证组中。结果当用户提交该页时,将检查该页上的所有验证程序(包括电话号码的那两个验证程序)。如果用户清除复选框,则将从该组移除这些验证程序,因此在单击“Submit Request”(提交申请)按钮时不处理这些验证程序。
测试条件验证
您现在可以测试该条件验证是否正常工作。
测试条件验证
按 Ctrl+F5 运行该页。
输入有效的电子邮件地址、团队人数和日期信息。
单击“Submit Request”(提交申请)。
随即将提交该页,并显示确认消息。
选择“Confirm reservation by phone”(通过电话确认预订)复选框。
再次单击“Submit Request”(提交申请)。
此时,会显示一条错误消息(电话文本框旁边带有一个星号)。在单击了复选框后,就启用了对该文本框的验证。
输入一个无效电话号码,然后再次单击 Submit Request 以确认该文本框不会接受无效电话号码。
输入一个格式正确的电话号码,然后单击提交按钮以确认验证程序控件接受格式良好的数据。
说明: 如果已为 RegularExpressionValidator 控件的 ValidationExpression 属性选择“正则表达式编辑器”中的“美国电话号码”,则格式正确的电话号码应包括区号(由 3 个数字字符组成的可选字段,括在括号中或后跟一个短划线),后跟一组 3 个数字字符、一个短划线加上一组 4 个数字字符。以下是一些有效的示例:(425) 555-0123、425-555-0123 或 555-0123。
后续步骤
添加到 Web 窗体页的验证演示了 Web 验证控件的基本概念。
执行验证一个重要方面是了解它如何帮助您增强网站的安全性。有关详细信息,请参见 Web 应用程序安全威胁概述