Problem You have two logical sections on a form with controls that require different validation as a function of the button the user clicks, such as a form that supports login and new user registration. Solution For each group of controls and its associated form-submit button, set the ValidationGroup attribute to a unique group name and set the CausesValidatio attribute of the form-submit buttons to TRue. In the .aspx file: Set the ValidationGroup attribute of a form-submit button to a unique group name. Set the ValidationGroup attribute of each of the controls to be validated when the button is clicked to the same group name as the form-submit button. Set the form-submit button's CausesValidation attribute to True to have validation performed when the button is clicked. Repeat steps 13 for each form-submit button and its associated controls. In the code-behind class for the page, use the .NET language of your choice to add code to the event handler for each button's click event to check the Page.IsValid property and verify that all validation was successful. (See Recipe 3.1 for details.) Figure 3-14 shows a typical form with normal, error-free output. Figure 3-15 shows the error message that appears on the form when a validation error occurs in the login section of the form. Figure 3-16 shows the error message that appears on the form when a validation error occurs in the form's register section. Examples 3-13, 3-14 through 3-15 show the .aspx and code-behind files for our application that implements the solution. Discussion In ASP.NET 1.x, handling multiple logical sections on a form with more than one submit button was difficult, especially when you needed different validation to be performed as a function of which button the user clicked. You generally had to resort to custom code to control the validation. Depending on the number of buttons and controls, this could result in some complex code. Figure 3-14. Form with group validation outputnormal Figure 3-15. Form with group validation outputfirst group failed validation Figure 3-16. Form with group validation outputsecond group failed validation In ASP.NET 2.0, all validators and form-submit buttons have an optional ValidationGroup attribute. Setting The ValidationGroup attribute of a submit button, and the controls to be validated when the button is clicked to the same group name, provides the ability to define what controls are validated with each button. This reduces the code required to support multisection forms. | Any controls that do not have the ValidationGroup attribute set to a value are grouped by default to provide backward compatibility with ASP.NET 1.x. |
|
Our example application has two sections on the form, one with login controls (login ID, password, and a login button) and the other with registration controls (login ID, email address, password, re-enter password, and a register button). The ValidationGroup attribute for each of the controls in the login section are set to LoginGroup. When the Login button is clicked, only the controls with the ValidationGroup set to LoginGroup are validated. <asp:CustomValidator Runat="server" Display="None" EnableClientScript="False" ErrorMessage="Login ID or Password Is Invalid" OnServerValidate="cvAuthentication_ServerValidate" ValidationGroup="LoginGroup" /> … <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtLoginID" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Login ID Is Required" ValidationGroup="LoginGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> … <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtPassword" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Password Is Required" ValidationGroup="LoginGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> … <input runat="server" type="button" value="Login" causesvalidation="true" onserverclick="btnLogin_Click" validationgroup="LoginGroup" > The ValidationGroup attribute for each of the controls in the registration section are set to RegisterGroup. When the Register button is clicked, only the controls with the ValidationGroup set to RegisterGroup are validated. <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtNewLoginID" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Login ID Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> … <asp:requiredfieldvalidator runat="server" controltovalidate="txtEmailAddress" css display="Dynamic" enableclientscript="True" ErrorMessage="Email Address Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:requiredfieldvalidator> <asp:RegularExpressionValidator Runat="server" ControlToValidate="txtEmailAddress" Css Display="Dynamic" EnableClientScript="True" ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" ErrorMessage="Invalid Email Address" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RegularExpressionValidator> … <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtPassword1" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Password Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> … <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtPassword2" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Re-Entered Password Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> <asp:CompareValidator runat="server" ControlToValidate="txtPassword2" ControlToCompare="txtPassword1" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Both Passwords Must Match" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:CompareValidator> … <input runat="server" type="button" value="Register" causesvalidation="true" onserverclick="btnRegister_ServerClick" validationgroup="RegisterGroup" > In addition to grouping buttons and user input controls, the ValidationSummary control supports the ValidationGroup attribute. This provides the ability to use a ValidationSummary for each section on the form and to display a summary of the errors in the appropriate section. <asp:ValidationSummary Runat="server" Css DisplayMode="BulletList" EnableClientScript="True" HeaderText="Error Summary" ValidationGroup="LoginGroup" /> When using validation groups, no custom code is required in client-side JavaScript or in the code-behind to support the validation. See Also Recipe 3.8 Example 3-13. Form with multiple validation sections (.aspx) <%@ Page Language="VB" MasterPageFile="~/ASPNetCookbookVB.master" AutoEventWireup="false" CodeFile="CH03GroupingValidatorsVB.aspx.vb" Inherits="ASPNetCookbook.VBExamples.CH03GroupingValidatorsVB" title="Grouping Validators" %> <asp:Content Runat="server" ContentPlaceHolder> <div align="center" > Grouping Validators (VB) </div> <table align="center" > </tr> <td colspan="2" align="left"> <asp:ValidationSummary Runat="server" Css DisplayMode="BulletList" EnableClientScript="True" HeaderText="Error Summary" ValidationGroup="LoginGroup" /> <asp:CustomValidator Runat="server" Display="None" EnableClientScript="False" ErrorMessage="Login ID or Password Is Invalid" OnServerValidate="cvAuthentication_ServerValidate" ValidationGroup="LoginGroup" /> </td> </tr> </tr> <td >Login ID: </td> <td> <asp:TextBox Runat="server" Columns="30" Css /> <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtLoginID" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Login ID Is Required" ValidationGroup="LoginGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> </td> </tr> </tr> <td >Password: </td> <td> <asp:TextBox Runat="server" TextMode="Password" Columns="30" Css /> <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtPassword" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Password Is Required" ValidationGroup="LoginGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> </td> </tr> </tr> <td colspan="2" align="center"> <br/> <input runat="server" type="button" value="Login" causesvalidation="true" onserverclick="btnLogin_Click" validationgroup="LoginGroup" /> </td> </tr> </table> <hr /> <table align="center" > </tr> <td colspan="2" align="left"> <asp:ValidationSummary Runat="server" Css DisplayMode="BulletList" EnableClientScript="True" HeaderText="Error Summary" ValidationGroup="RegisterGroup" /> </td> </tr> </tr> <td >Login ID: </td> <td> <asp:TextBox Runat="server" Columns="30" Css /> <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtNewLoginID" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Login ID Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> </td> </tr> </tr> <td >Email Address: </td> <td> <asp:TextBox Runat="server" Columns="30" Css /> <asp:requiredfieldvalidator runat="server" controltovalidate="txtEmailAddress" css display="Dynamic" enableclientscript="True" ErrorMessage="Email Address Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:requiredfieldvalidator> <asp:RegularExpressionValidator Runat="server" ControlToValidate="txtEmailAddress" Css Display="Dynamic" EnableClientScript="True" ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" ErrorMessage="Invalid Email Address" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RegularExpressionValidator> </td> </tr> </tr> <td >Password: </td> <td> <asp:TextBox Runat="server" TextMode="Password" Columns="30" Css /> <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtPassword1" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Password Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> </td> </tr> </tr> <td >Re-enter Password: </td> <td> <asp:TextBox Runat="server" TextMode="Password" Columns="30" Css /> <asp:RequiredFieldValidator Runat="server" ControlToValidate="txtPassword2" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Re-Entered Password Is Required" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:RequiredFieldValidator> <asp:CompareValidator runat="server" ControlToValidate="txtPassword2" ControlToCompare="txtPassword1" Css Display="Dynamic" EnableClientScript="True" ErrorMessage="Both Passwords Must Match" ValidationGroup="RegisterGroup" > <img src="/books/1/505/1/html/2/images/arrow_alert.gif" alt="arrow"/> </asp:CompareValidator> </td> </tr> </tr> <td colspan="2" align="center"> <br/> <input runat="server" type="button" value="Register" causesvalidation="true" onserverclick="btnRegister_ServerClick" validationgroup="RegisterGroup" /> </td> </tr> </table> </asp:Content> | Example 3-14. Form with multiple validation sections (.vb) Option Explicit On Option Strict On Imports System.Configuration.ConfigurationManager Imports System.Data Imports System.Data.OleDb Namespace ASPNetCookbook.VBExamples ''' <summary> ''' This class provides the code behind for ''' CH03GroupingValidatorsVB.aspx ''' </summary> Partial Class CH03GroupingValidatorsVB Inherits System.Web.UI.Page '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the authentication server ''' validate event. It is responsible for checking the login ID and ''' password in the database to authenticate the user. ''' </summary> ''' ''' <param name="source">Set to the sender of the event</param> ''' <param name="args">Set to the event arguments</param> Protected Sub cvAuthentication_ServerValidate(ByVal source As Object, _ ByVal args As ServerValidateEventArgs) Dim dbConn As OleDbConnection = Nothing Dim dCmd As OleDbCommand = Nothing Dim strConnection As String Dim strSQL As String Try 'initially assume credentials are invalid args.IsValid = False 'get the connection string from web.config and open a connection 'to the database strConnection = _ ConnectionStrings("dbConnectionString").ConnectionString dbConn = New OleDb.OleDbConnection(strConnection) dbConn.Open( ) 'build the query string and check to see if a user with the entered 'credentials exists in the database strSQL = "SELECT AppUserID FROM AppUser " & _ "WHERE LoginID=? AND " & _ "Password=?" dCmd = New OleDbCommand(strSQL, dbConn) dCmd.Parameters.Add(New OleDbParameter("LoginID", _ txtLoginID.Text)) dCmd.Parameters.Add(New OleDbParameter("Password", _ txtPassword.Text)) 'check to see if the user was found If (Not IsNothing(dCmd.ExecuteScalar( ))) Then args.IsValid = True End If Finally 'cleanup If (Not IsNothing(dbConn)) Then dbConn.Close( ) End If End Try End Sub 'cvAuthentication_ServerValidate '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the login button click ''' event. It is responsible for processing the form data for login. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub btnLogin_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) If (Page.IsValid) Then 'user has been authenticated so proceed with allowing access 'to the site End If End Sub 'btnLogin_Click '''*********************************************************************** ''' <summary> ''' This routine provides the event handler for the login button click ''' event. It is responsible for processing the form data for ''' registration. ''' </summary> ''' ''' <param name="sender">Set to the sender of the event</param> ''' <param name="e">Set to the event arguments</param> Protected Sub btnRegister_ServerClick(ByVal sender As Object, _ ByVal e As System.EventArgs) If (Page.IsValid) Then 'all entered data is valid so proceed with registration End If End Sub 'btnRegister_ServerClick End Class 'CH03GroupingValidatorsVB End Namespace | Example 3-15. Form with multiple validation sections (.cs) using System; using System.Configuration; using System.Data; using System.Data.OleDb; namespace ASPNetCookbook.CSExamples { /// <summary> /// This class provides the code behind for CH03GroupingValidatorsCS.aspx /// </summary> public partial class CH03GroupingValidatorsCS : System.Web.UI.Page { ///*********************************************************************** /// <summary> /// This routine provides the event handler for the authentication server /// validate event. It is responsible checking the login ID and password /// in the database to authenticate the user. /// </summary> /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void cvAuthentication_ServerValidate(Object source, System.Web.UI.WebControls.ServerValidateEventArgs args) { OleDbConnection dbConn = null; OleDbCommand dCmd = null; String strConnection = null; String strSQL = null; try { // initially assume credentials are invalid args.IsValid = false; // get the connection string from web.config and open a connection // to the database strConnection = ConfigurationManager. ConnectionStrings["dbConnectionString"].ConnectionString; dbConn = new OleDbConnection(strConnection); dbConn.Open( ); // build the query string and check to see if a user with the // entered credentials exists in the database strSQL = "SELECT AppUserID FROM AppUser " + "WHERE LoginID=? AND " + "Password=?"; dCmd = new OleDbCommand(strSQL, dbConn); dCmd.Parameters.Add(new OleDbParameter("LoginID", txtLoginID.Text)); dCmd.Parameters.Add(new OleDbParameter("Password", txtPassword.Text)); // check to see if the user was found if (dCmd.ExecuteScalar( ) != null) { args.IsValid = true; } } // try finally { // cleanup if (dbConn != null) { dbConn.Close( ); } } // finally } // cvAuthentication_ServerValidate ///*********************************************************************** /// <summary> /// This routine provides the event handler for the login button click /// event. It is responsible for providing access to the site for the /// user if authenticated. /// </summary> /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void btnLogin_Click(Object sender, System.EventArgs e) { if (Page.IsValid) { // user has been authenticated so proceed with allowing access // to the site } } //btnLogin_Click ///*********************************************************************** /// >summary> /// This routine provides the event handler for the register button click /// event. It is responsible for processing the form data for /// registration. /// </summary> /// <param name="sender">Set to the sender of the event</param> /// <param name="e">Set to the event arguments</param> protected void btnRegister_ServerClick(Object sender, System.EventArgs e) { if (Page.IsValid) { // all entered data is valid so proceed with registration } } //btnRegister_ServerClick } // CH03GroupingValidatorsCS } | |