Home > Uncategorized > Using Validation Application Block in ASP.NET

Using Validation Application Block in ASP.NET

Any web page which requires input from the user simply cant allow just any data to be entered because the data might be too long, missing or incorrect. We need to validate the data entered by the users in a number of ways; for example, First Name and Last Name might be required fields and Date of Birth cannot be greater than the current date etc. We can very well use the client side validators provided by ASP.NET like RequiredFieldValidator, CompareValidator or RegularExpressionValidtor but is that really enough? What if JavaScript is disabled by the client? What if we need to validate our business objects? It is often important to validate data several times within the same application. For example, you may need to validate object instances that you:

  • Generate in separate tiers or components of your application
  • Retrieve from a cache, a repository, or a third-party data access layer
  • Receive from a Web Service as an object instance or a set of property values
  • Reconstruct from existing values, perhaps populating them by copying properties from a similar object or using values retrieved from a database

Enter the Enterprise Library with its Validation Application Block.

The Validation Application Block is designed to address the most common tasks developers face when they must validate input either from a user or another system. The Validation Application Block provides a comprehensive series of validation components that you can apply through configuration, or through attributes applied directly to classes, class members, plus UI controls for use in both ASP.NET and Windows Forms applications.

One of the major advantages with Validation Application Block is that you can define rule sets within your application configuration file, with each rule set defining the types of validation to undertake and the individual parameters for that validation process. This means that administrators can quickly and easily change the validation rules and parameters without requiring any changes to the existing code – avoiding the risk of code errors, recompilation issues, and application downtime.

The Validation Application Block is designed to do the following:

  • Encapsulate the logic used to perform the most common validation tasks into minimal application code.
  • Relieve developers of the requirement to write duplicate code and custom code for common validation tasks.
  • Allow validation rules to be changed after the application has been deployed, and ensure that changes happen simultaneously and consistently.

There are four ways that you can associate validators with your types:

  • You can use configuration.
  • You can use attributes.
  • You can use a combination of configuration and attributes.
  • You can use self validation, which means that you include validation logic within the object you want to validate.

The Validation Application Block contains a wide range of validators that you can use to check almost any type of property or value. The built-in validators include:

  • Range Validators –
    • Range Validator – checks that a value falls within a specified range. The range may be either closed, which means it has both a lower and an upper bound specified, or open, which means that it only has one bound specified. The Range Validator can be used with any type that implements the IComparable interface. This includes all numeric types and strings. While it is possible, in code, to use this validator with DateTime types, the Date Time Range Validator may be a better choice because it allows you to take advantage of attributes and configuration.
    • Date Time Range Validator – checks that a DateTime object falls within the specified range.
    • String Length Validator – checks that the length of the string is within the specified range. The range may include or exclude the endpoints by omitting the lower or upper bound.
  • String Validators
    • Contains Characters Validator – checks that an arbitrary string, such as a string entered by a user in a Web form, contains any or all of the characters that are specified by the CharacterSet property.
    • Regular Expression Validator – checks that the value matches the pattern specified by a regular expression.
    • Type Conversion Validator – checks that a string can be converted to a specific type. For example, the validator can check that "6.32" can be converted to a Double type or that "2007-02-09" can be converted to a DateTime type.
  • Set Validators
    • Domain Validator – checks that a value is one of the specified values in a specified set. For example, it can check that a name is "Tom," "Dick," "Harry," or "George" or that an integer is 2, 3, 5, 7, or 11. If the set only contains one value, you can use this validator to check for equality.
    • Enum Conversion Validator – checks that a string can be converted to a value in a specified enum type. For example, it can check that "Blue" can be converted to a value in the Color enumeration.
  • Comparison Validators
    • Property Comparison Validator – compares the value to be checked with the value of a property. For example, a n AuctionItem object, the current bid is greater than or equal to the minimum bid.
    • Relative Date Time Validator – checks that the DateTime value falls within a specified range using relative times and dates.
  • Object Validators
    • Not Null Validator – checks that the value is not null.
    • Object Validator – causes validation to occur on an object reference. All validators defined for the object’s type will be invoked, just as if the Validation.Validate method had been called on the object. If the object you want to validate is null, the validation is ignored. If the reference is to an instance of a type that is not compatible with the configured target’s type, the validation fails. This validator is helpful for validating tree-structured data.
    • Object Collection Validator – checks that the object is a collection of the specified type and then invokes validation on each element of the collection. If the object you want to validate is null, the validation is ignored. If the object you want to validate is not a collection, then the validation fails and the rule set is not applied. If there are elements in the collection that are of a different type than the one you specified for the object, then the validation for these elements fails but this does not affect validation for the other elements.

The Validation Application Block also provides the following composite validators which allow you to combine other validators by nesting them within this type of validator to create complex validation rules.

  • And Composite Validator – requires that all the validators that make up the composite validator be true. For example, you can use the And Composite Validator to require that the Not Null Validator AND the Date Time Range Validator be True. Because the Validation Application Block’s default behavior is to AND validators, you only need this validator to implement complex logic.
  • Or Composite Validator – requires that at least one of the validators that make up the composite validator be True. For example, you can use the Or Composite Validator to require that the Not Null Validator OR the Date Time Range Validator be True.

Each validator also has a Negated property, which reverses the operation of the validator so that it returns False if the value is valid, and True if not. This is useful when you combine validators using the And Composite Validator and the Or Composite Validator.

Assume that our customer entity is as follows and we want to validate the fields within this object for some business rules. For example, Postal Code format nnnnn[-nnnn] etc.

public class Customer { public string Name { get; set; } public string Address { get; set; } public string City { get; set; } public string PostalCode { get; set; } public int EmployeeCount { get; set; } public DateTime LastReportDate{ get; set; } }

The first step when using the Validation Application Block is to create rule set(s) for our type / object. To create a rule set for an object, you must first create and compile that assembly. Once you have a target object class, open the configuration file for your application in the Configuration Editor integrated within Visual Studio by right-clicking on the Web.config file in the Solution Explorer window and select Edit Enterprise Library Configuration.

In the configuration editor, right click on the application node and select New, then click Validation Application Block to add the Validation Application Block to your application. Then right-click on the new Validation Application Block node, select New, and click Type. In the Type Selector dialog, click the Load an assembly button and navigate to the folder containing your target object. Click Open to load this assembly. Find your target assembly in the list and select the target class to which you want to attach a rule set.

Click OK, and the class appears in the configuration under the Validation Application Block node. Now you are ready to create the rule set.

Right-click on the new target object node in the configuration editor, select New, and click Rule Set. Change the name of the rule set as required – you will use the name in your code so you should specify a name that will help you to read and debug your code, especially if you define more than one rule set.

The next stage is to select the members of the target object that you want to validate. Right-click on the new rule set node, select New, and click Choose Members to display a dialog containing all the public members of the target object. Select the required members and click OK to close the dialog and add these members to the rule set.

You now have a hierarchy that contains the list of members to which you will add validators. For each target object member, right-click on it, select New, and click the type of validator you want to add. As you add each one, use the Properties window in Visual Studio to set the properties you require for each validator.

For example, the CompanyAddress property has a String Length Validator attached with the following properties set:

<validation> <type assemblyName="TestApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="TestApp.Customer"> <ruleset name="ExampleRuleSet"> <properties> <property name="Name" > <validator lowerBound="5" lowerBoundType="Inclusive" upperBound="100" upperBoundType="Inclusive" negated="false" messageTemplate="Customer address must be between 5 and 100 characters" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerAddressValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="String Length Validator"/> </property> <property name="Address"> <validator lowerBound="5" lowerBoundType="Inclusive" upperBound="100" upperBoundType="Inclusive" negated="false" messageTemplate="Customer address must be between 5 and 100 characters" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerAddressValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="String Length Validator"/> </property> <property name="City"> <validator lowerBound="2" lowerBoundType="Inclusive" upperBound="30" upperBoundType="Inclusive" negated="false" messageTemplate="City name must be between 2 and 30 characters" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerCityValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="String Length Validator"/> </property> <property name="PostalCode"> <validator pattern="\d{5}(-\d{4})?" options="None" patternResourceName="" patternResourceType="" messageTemplate="Postal code must be in the form nnnnn[-nnnn]" messageTemplateResourceName="" messageTemplateResourceType="" tag="CustomerPostalCodeValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.RegexValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Regex Validator"/> </property> <property name="EmployeeCount"> <validator lowerBound="1" lowerBoundType="Inclusive" upperBound="100" upperBoundType="Inclusive" negated="false" messageTemplate="Employee count must be between 1 and 100" messageTemplateResourceName="" messageTemplateResourceType="" tag="EmployeeCountValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.RangeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Range Validator"/> </property> <property name="LastReportDate"> <validator lowerBound="2007-01-01" lowerBoundType="Inclusive" upperBound="2008-03-28" upperBoundType="Inclusive" negated="false" messageTemplate="Report Date must be between 1st Jan and 31st Dec 2007" messageTemplateResourceName="" messageTemplateResourceType="" tag="LastReportDateValidator" type="Microsoft.Practices.EnterpriseLibrary.Validation.Validators.DateTimeRangeValidator, Microsoft.Practices.EnterpriseLibrary.Validation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Date Range Validator"/> </property> </properties> </ruleset> </type> </validation>

ASP.NET integration uses a class named PropertyProxyValidator, which implements a control that you can use within an ASP.NET Web page to perform UI validation. This control inherits from the ASP.NET validation control base class named BaseValidator, and is therefore effectively an ASP.NET validation control.

The BaseValidator class exposes properties such as ControlToValidate, Display (None, Static, Dynamic), EnableClientScript, Enabled, IsValid, SetFocusOnError, and ValidationGroup. The PropertyProxyValidator class also exposes the Validate method, which you can use to initiate validation of specific validators if required. However, all the instances of the PropertyProxyValidator class you place in a page integrate with the ASP.NET validation system, and so you can cause validation by calling the Validate method of the Page class, and check the result using the IsValid property of the Page class – this does not occur automatically.

By integrating the Validation Application Block with your applications, you can reuse your validation rules across several levels of your system architecture. Integration allows you reuse the validators that are associated with your application classes when you perform validation at the user-interface level for ASP.NET . The integration provided by the Validation Application Block at the user-interface level does the following:

  • It provides a way to associate properties of validated application objects with user-interface controls.
  • It provides a way to convert values from an input data type to an application-specific data type. For example, you can convert a string input to a System.DateTime value.
  • It helps avoid coding errors in type names and property names. For example, it throws exceptions when type names or property names cannot be found.
  • It does not require instances of application objects to be created in order for validators to be invoked at the user-interface level. In other words, you do not need to instantiate a Customer object just to check whether an input string entered by the user meets the validation requirements of the Customer.Name property.

To use the PropertyProxyValidator class, you simply add instances to the ASP.NET page, either by declaring them within the .aspx file or by generating instances dynamically at runtime and adding them to the Controls collection of the Page object or another container control. The process is identical to adding ASP.NET built-in validation controls such as the RequiredFieldValidator or any other ASP.NET control) to a page.

The only real differences when working with the Validation Application Block compared to the ASP.NET validation controls are:

  • You must include an @Register directive in the ASP.NET page to register the integration assembly that contains the PropertyProxyValidator control:
    <%@ Register Assembly="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet" Namespace="Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet" TagPrefix="EntLibValidators" %>
  • You use only one type of validation control, the PropertyProxyValidator control, for all validation operations. The actual operation and parameters appear in the configuration file or in attributes applied to the target object class and its members. You should have a target object class defined that supports validation through configuration or attributes.
  • You specify the name of the rule set, the type name of the target object, and the target object member (method or property name) in the PropertyProxyValidator control declaration. For example:
<EntLibValidators:PropertyProxyValidator ID="CustomerNameValidator" runat="server" ControlToValidate="txtName" PropertyName="Name" RulesetName="ExampleRuleSet" SourceTypeName="TestApp.Customer" EnableViewState="false"/>

For each validated UI input control, specify that input control’s ID property as the ControlToValidate property of the PropertyProxyValidator control. Also set the RulesetName, SourceTypeName, and PropertyName properties to the appropriate values based on your application configuration.

Our test application displays textboxes for the six properties of the target object. If you click the Submit button, after entering values in the text boxes, the code creates an instance of the target class with valid values, performs validation on the object, and displays the property values and the validation result in the page.

If you now edit the values in the text boxes so that they are outside the range of valid values, and click the Submit button again, the page displays a list of errors it encounters when validating the new object instance.

For each invalid property value, the page displays the contents of the MessageTemplate for the validator, the name of the target property, the value of the Tag property of the validator, and the type name of the target object.

To validate the UI control values, add code to the handler for the button or other control that submits the page. A separate routine named CreateLocalCompanyObject performs the task of applying the validated UI values to a new instance of the target object, and displaying its properties in the page:

// force validators to check control values Page.Validate(); if (Page.IsValid) { // create sample object instance and set properties CreateLocalCustomerObject(); } else { lblResult.Text = "Validation errors encountered by ASP.NET Integration Validators<p />"; }
private void CreateLocalCustomerObject() { // create sample object instance and set properties TestApp.Customer objCustomer = new TestApp.Customer(); objCustomer.Name = txtName.Text; objCustomer.Address = txtAddress.Text; objCustomer.City = txtCity.Text; objCustomer.PostalCode = txtPostalCode.Text; objCustomer.EmployeeCount = Int32.Parse(txtEmployees.Text); objCustomer.LastReportDate = DateTime.Parse(txtReportDate.Text); // display and validate property values DisplayAndValidateSampleObject(objCustomer); }

Unlike the ASP.NET UI validation controls, which react to an event in the ASP.NET page cycle to perform validation, the Validation Application Block validators must be explicitly executed by calling the static Validate method of the block. The easiest way to do this is to use the Validation façade. The façade allows you to you to create a Validator instance and validate an object with a single line of code. This is shown in the following code example.

Customer cust = new Customer(); ValidationResults results = Validation.Validate<Customer>(cust, "rulesetname");

If you do not want to use the façade, you can use the following code, which is the equivalent.

Customer cust = new Customer(); Validator<Customer> validator = ValidationFactory.CreateValidator<Customer>("rulesetname"); ValidationResults results = validator.Validate(cust);

Use the CreateValidator method on the ValidationFactory class to first get a reference to the Validator instance, and then use the Validate method to validate the object.

The Validate method of the Validation façade accepts as parameters the name of the object to validate, and optionally the names of the validation rule sets to apply. For example, if you have only a single rule set named RuleSetA defined in the configuration of the application, you can apply this rule set to an object named customer using the following code.

ValidationResults results = Validation.Validate(cust, "RuleSetA");

If you have two rule sets named RuleSetA and RuleSetB defined in the configuration of the application, you can apply the rules from both using the following code.

ValidationResults results = Validation.Validate(cust, "RuleSetA", "RuleSetB");

The Validate method returns an instance of the ValidationResults class, which is a collection containing a ValidationResult instance for each validation failure. The ValidationResult class exposes properties that allow you to obtain the value of the Key (the member name if available), the Message describing the validation error, the value of the validator Tag property, the type name of the Target object, and the name of the Validator. There is also the NestedValidationResults property, which exposes a ValidationResults collection containing the validation errors for any nested validators, when using a composite validator.

Our DisplayAndValidateSampleObject() function calls the Validate method, and then checks if there were any validation errors by examining the IsValid property of the returned ValidationResults collection. If there are errors, the code iterates through the collection adding the values of the Key, Tag, and Target properties of each ValidationResults instance to the StringBuilder. If there are no errors, it adds a suitable message to the StringBuilder instead. Finally, the code displays the contents of the StringBuilder in a Label control on the page:

... // validate the property values using the configured rule set ValidationResults results; results = Validation.Validate(targetObject, "ExampleRuleSet"); // get validation results if (!results.IsValid) { builder.Append("<b>Validation Errors:</b>:<br />"); foreach (ValidationResult result in results) { builder.Append(String.Format("- <b>{0}</b><br />", result.Message)); builder.Append(String.Format("&nbsp; (Key: {0}, ", result.Key.ToString())); builder.Append(String.Format("Tag: {0}, ", result.Tag)); builder.Append(String.Format("Target: {0})<br />", result.Target.ToString())); } } else { builder.Append("All object property values are valid."); } // display results in Label control lblResult.Text = builder.ToString(); ...

It is always a good idea to repeat on the server any UI validation you carry out before using posted values in your application. This protects against spoofing attacks; and against issues that may arise is client browsers do not fully support or correctly process client-side script. However, unlike the ASP.NET validation controls, the PropertyProxyValidator controls only perform validation server-side, and not through client-side script.

Using the Enterprise Library Validation Application Block in ASP.NET applications allows concentrating on the use of rule sets that allow validation across the UI and object instances within the application tiers.

While ASP.NET provides a fully-featured set of UI validation controls, these do not always fulfill the requirements of enterprise-level applications. The Validation Application Block supports a wider range of validators, has features to allow composition and negation of validators, and supports validation using configuration rules as well as attributes applied directly to classes and class members.

One should combine the Validation Application Block validators with the ASP.NET built-in validators as required. The PropertyProxyValidator control that supports ASP.NET integration is itself a descendant of the ASP.NET validator base class, and so behaves and can be handled in the same way as the ASP.NET validation controls.

 

Advertisements
  1. Unknown
    July 14, 2008 at 4:35 pm

    Excellent coverage on VAB. Can you also mention about setting up development environment? I have installed EntLib 4.0, then referenced Common, Data and Validator App block Dll from installed location(not GAC) and try to build project….I get following error. I found a workaround to get it going by removing PublicKey token from EntLib config file, but I guess its not right way."Could not load file or assembly \’Microsoft.Practices.EnterpriseLibrary.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35\’ or one of its dependencies. The located assembly\’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) "

  2. Unknown
    July 14, 2008 at 4:37 pm

    A little correction, I get above error at runtime.

  3. Misbah
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: