Configurable properties of a control are properties whose values can be set in the <appSettings> section of the Web application's configuration file, web.config, rather than in every page that uses an instance of the control. These are similar to but not exactly the same as dynamic properties in Visual Studio .NET, which do not apply to server controls. A control can implement configuration support for properties that need to be consistent across the entire application or for properties that might need to be maintained and changed by an administrator once the application has been implemented and deployed. Such properties include database connection strings and names of server resources. In this section, we will implement a new validator control, PhoneNumberValidator , which uses regular expressions to validate phone numbers . This control implements the validation expression as a configurable property so that the pattern for a valid phone number can be defined once across the entire Web application and easily updated. We described how to implement custom validator controls in Chapter 14, "Validator Controls." Listing 17-14 lists the page used to test the PhoneNumberValidator control. Listing 17-14 PhoneNumberValidatorTest.aspx<%@Pagelanguage="c#" %> <%@RegisterTagPrefix="msp" Assembly="MSPress.ServerControls" Namespace="MSPress.ServerControls" %> <html> <scriptrunat="server"> protectedvoidButton1_Click(objectsender,EventArgse){ if(Page.IsValid){ Label1.Text= "Youentered: " +TextBox1.Text; } } </script> <head> <title>PhoneNumberValidatorSample</title> </head> <body> <formmethod="post" runat="server" ID="Form1"> <p> Enteraphonenumber: <br/> <asp:TextBoxid="TextBox1" runat="server" Columns="25"/> <msp:PhoneNumberValidatorid="PhoneNumberValidator1" runat="server" ControlToValidate="TextBox1" ErrorMessage="Enteravalidphonenumberinthetextbox.It mustbein(###)###-####x####format.Theextensionisoptional." Text="Enteravalidphonenumber." /> <br/> <asp:Buttonid="Button1" runat="server" Text="Submit" OnClick="Button1_Click"/> <br/> <asp:Labelid="Label1" runat="server" /> <br/> <asp:ValidationSummaryrunat="server" HeaderText="Errors:" id="Validationsummary1"/> </p> </form> </body> </html> Listing 17-15 lists the contents of the web.config file from the Chapter17 folder of the BookWeb Web application. The file defines an < appSettings > value that specifies the validation pattern that the PhoneNumberValidator control should use. The validation pattern shown matches that of standard U.S. phone numbers with an optional area code and optional extension. Figure 17-5 shows PhoneNumberValidator at work on a Web page. Listing 17-15 The web.config file in the Chapter17 folder that defines the pattern used for phone number validation<?xmlversion="1.0" encoding="utf-8" ?> <configuration> <appSettings> <add key="MSPress.ServerControls.PhoneNumberValidator.Validation Expression" value="((\(\d{3}\)?)(\d{3}-))?\d{3}-\d{4}(x\d{1,4})?"/> </appSettings> </configuration> Figure 17-5. The PhoneNumberValidatorTest.aspx page containing the validator in its invalid state
Listing 17-16 contains the code for the PhoneNumberValidator control. Listing 17-16 PhoneNumberValidator.csusingSystem; usingSystem.Collections; usingSystem.ComponentModel; usingSystem.Configuration; usingSystem.Text.RegularExpressions; usingSystem.Web.UI; usingSystem.Web.UI.WebControls; namespaceMSPress.ServerControls{ [ ToolboxData("<{0}:PhoneNumberValidatorrunat=\"server\" " + "ErrorMessage=\"PhoneNumberValidator\" " + "Text=\"*\"></{0}:PhoneNumberValidator>") ] publicclassPhoneNumberValidator:BaseValidator{ privateconststringappSettingsKey= "MSPress.ServerControls.PhoneNumberValidator.Validation Expression"; privateconststringdefaultExpression= @"((\(\d{3}\)?)(\d{3}-))?\d{3}-\d{4}"; privateboolInDesignMode{ get{ if(Site!=null){ returnSite.DesignMode; } returnfalse; } } [ Category("Behavior"), DefaultValue(defaultExpression), Description("Theregularexpressionusedtovalidatephonenumbers") ] publicstringValidationExpression{ get{ strings=null; s=(string)ViewState["ValidationExpression"]; if((s!=null)&&(s.Length!=0)){ //It'sbeensetonthiscontrolinstance. returns; } if(InDesignMode==false){ s=ConfigurationSettings.AppSettings[ appSettingsKey]; if((s!=null)&&(s.Length!=0)){ //Usethevaluespecifiedinconfiguration. returns; } } //Resorttothedefault,whichallows //(###)###-####or###-###-####or###-####. returndefaultExpression; } set{ if((value!=null)&&(value.Length!=0)){ try{ //Doatestmatchtovalidatetheexpression. Regex.Match(String.Empty,value); } catch{ thrownewArgumentException("Invalidregularexpression", "value"); } } ViewState["ValidationExpression"]=value; } } protectedoverridevoidAddAttributesToRender(HtmlTextWriterwriter){ base.AddAttributesToRender(writer); if(RenderUplevel){ //Rendertheattributesneededfor //RegularExpressionValidatorclient-sidefunctionality. writer.AddAttribute("evaluationfunction", "RegularExpressionValidatorEvaluateIsValid",false); writer.AddAttribute("validationexpression", ValidationExpression); } } protectedoverrideboolEvaluateIsValid(){ //Getthevaluetobevalidated. stringcontrolValue= GetControlValidationValue(ControlToValidate); if(controlValue==null){ //Impliesthatthevalidatorisnotboundtoacontrol. returntrue; } controlValue=controlValue.Trim(); try{ Matchm= Regex.Match(controlValue,ValidationExpression); //Mustmatch,andthematchmustspanacrossthe //entirevalue. return(m.Success&&(m.Index==0)&& (m.Length==controlValue.Length)); } catch{ returnfalse; } } } } In an ideal world, this validator control would derive from the ASP.NET RegularExpressionValidator class. However, the ValidationExpression property of that class is nonvirtual and cannot be overridden to add configuration support. Hence, PhoneNumberValidator derives directly from the BaseValidator class and includes the functionality of RegularExpressionValidator . In its implementation of the EvaluateIsValid method, PhoneNumberValidator uses the regular expression “matching functionality provided by the System.Text.RegularExpressions.Regex class. The most interesting aspect of this class is the implementation of the ValidationExpression property, which demonstrates the following aspects of configurable properties:
Ordinary properties can be turned into configurable properties at any point. The property construct allows you to add this support, without requiring changes in any existing code that uses this property. |