henryjwr

See also: Other Geeks@INDC

May 2008 - Posts

Try and Catch Security Application Block

Try and Catch Security Application Block

Just Like my previous post, i wrote this in MS.Word and the picture is not show when i pasted it to this pane..[:'(], I have attach file

 

The Security Application Block was created to simplify and standardized the way that applications authorized and cache security information within an application.

Look and Feel Security Application Block Design

If we look closely Security Application Block was design with flexibility to implement different security issue in an application and also provide most standard security implementation. Security Application Block profiles the user information that could be used in form of context.

Figure  SEQ Figure \* ARABIC 25 Authorization Object Model

 

Figure  SEQ Figure \* ARABIC 26 SecurityCache Object Model

Let’s examine the each of the class that involve in the object model.

The AuthorizationFactory is the class that you could get the authorization provider. There are two implementations of the provider AzManAuthorizationProvider and AuthorizationRuleProvider. AzMan (Authorization Manager) provider provide standard interface to maintain Active Directory, roles groups, tasks and operations. The AzManAuthorizationProvider provide functionality that easy determine the authorization from the user identity information. On the other hand AuthorizationRuleProvider determine authorization with defined rule for each task or operation.

Figure  SEQ Figure \* ARABIC 27 AuthorizationFactory

Figure  SEQ Figure \* ARABIC 28 AzManAuthorizationProvider

Figure  SEQ Figure \* ARABIC 29 AuthorizationRuleProvider

Authorization need to use information to authenticated user with their profile. This information basically store in stateless storage. The user should be verified whenever one or more requests have been made to the server or application. These processes could hit the performance.  Security Application Block will help this problem with solution via cache. The Security Application Block cache the user profile so it could be use throughout application.

Figure  SEQ Figure \* ARABIC 30 SecurityCacheFactory

Like AuthorizationFactory Security Application Block provide Factory design pattern to get Cache Store Provider via SecurityCacheFactory.

Figure  SEQ Figure \* ARABIC 31 CachingStoreProvider

The CachingStoreProvider responsibilities to return user profile information. It could return user identity and principal that has been defined in their profile.

Unlock Security Application Block

I will show you how to implementing Rule Provider using AuthorizationRuleProvider.

1.       First create application configuration.

2.       Edit the application with Enterprise Library Configuration Editor.

3.       Add Security Application Block to the configuration

Action :: App Config Root >> New >> Security Application Block

You could only create one Security Application Block per application level.

4.       Creating Authorization Rule Provider, by right click the Authorization node.

Action :: Authorization >> New >> Authorization Rule Provider

This will create Rule Provider Node. You could rename the rule provider. Let’s say you rename it to “MyTestRuleProvider”.  You could have more than one Authorization Rule Provider in the application.

5.       Next Add Rule to the Rule Provider that has been created before.

Action :: Rule Provider >> New >> Rule

Rename the rule to “MyTestRule”.

6.       Each Rule has expression that defines the rule algorithm. Define the rule expression by click the ellipsis button in the expression property.  This action will show us Rule Expression Editor.

Figure  SEQ Figure \* ARABIC 32 Rule Expression Editor

In the Rule Expression Editor there are many buttons that you could use to create expression for the rule. The rule expression logic defines Identity and Principle that will be authenticated. Let’s assume we define that only Identity of henry, ela and role Manager that should be allowed other will denied. We could test the expression with given value.

7.       Close the Enterprise Library Configuration Editor. You will see that Enterprise Library Configuration Editor will update the application configuration.

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <configSections>

    <section

      name="securityConfiguration"

      type="Microsoft.Practices.EnterpriseLibrary.Security.Configuration.

SecuritySettings,

            Microsoft.Practices.EnterpriseLibrary.Security,

            Version=3.1.0.0,

            Culture=neutral,

            PublicKeyToken=b03f5f7f11d50a3a" />

    <section

      name="dataConfiguration"

      type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.

DatabaseSettings,

            Microsoft.Practices.EnterpriseLibrary.Data,

            Version=3.1.0.0,

            Culture=neutral,

            PublicKeyToken=b03f5f7f11d50a3a" />

  </configSections>

  <securityConfiguration

    defaultAuthorizationInstance=""

    defaultSecurityCacheInstance="">

    <authorizationProviders>

      <add

        type="Microsoft.Practices.EnterpriseLibrary.Security.

AuthorizationRuleProvider,

              Microsoft.Practices.EnterpriseLibrary.Security,

              Version=3.1.0.0,

              Culture=neutral,

              PublicKeyToken=b03f5f7f11d50a3a"

        name="MyTestRuleProvider">

        <rules>

          <add

            expression="(I:henry OR I:ela) AND R:Manager "

            name="MyTestRule" />

        </rules>

      </add>

    </authorizationProviders>

  </securityConfiguration>

</configuration>

Figure  SEQ Figure \* ARABIC 33 Enterprise Library Configuration Editor

8.       After finishing the configuration let create code that consume the configuration class.

You will need to add two references in this code.

o   System.Security.dll

This will provide Identity and Principal object.

o   Microsoft.Practices.EnterpriseLibrary.Security.dll

This will provide Authorization Provider.

                This the code snippet

using System;

using System.Collections.Generic;

using System.Text;

 

using System.Security.Principal;

using Microsoft.Practices.EnterpriseLibrary.Security;

 

namespace UsingSecurityApplicationBlock

{

    class Program

    {

        static void Main(string[] args)

        {

            TestAuthorization();

        }

 

        public static void TestAuthorization()

        {

            IPrincipal principle = new GenericPrincipal(

                new GenericIdentity("henry"), new string[] { "Manager" });

 

            IAuthorizationProvider provider =

                AuthorizationFactory.GetAuthorizationProvider(

"MyTestRuleProvider");

            bool authorized = provider.Authorize(principle, "MyTestRule");

 

            if (authorized)

                Console.WriteLine("You are authorized to use this...");

            else

                Console.WriteLine("You are not authorized to use this...");

           

            Console.WriteLine("Press any key to exit!");

            Console.ReadLine();

        }

    }

}

First we create principle object that pass IIdentity and array of string role. Create instance of IAuthorizationProvider pass the rule provider name. Call Authorize method to invoke authentication process. This method returns bool value whether the authentication failed or succeeded.

We have seen how to implement Authorization using Security Application Block, let’s move to use cache with Security Application Block.

Using Cache Store provider we could retrieve and save information regarding user profile.

1.       If you follow the step of creating Rule Provider, you could edit the file by Enterprise Library Editor too.

2.       Create Caching Store Provider

Action :: Security Cache Node >> New >> Caching Store Provider

This action will create Caching Store Provider node.

These node have properties like this:

Property Name

Description

Name

Caching Store Provider name

AbsoluteExpiration

Number of minutes in which the added object expires and is remove from the cache

CacheManager

Name

Description

ExpirationPollFrequencyInSeconds

Interval of checking expirations

MaximumElementsInCacheBeforeScavenging

Maximum number of cache items stored before scavenging occurs

Name

Cache Manager name

NumberToRemoveWhenScavenging

Number of cache items to remove when scavenging occurs

SlidingOperation

The number of minutes between the time added object was last accessed and when object expires

Figure  SEQ Figure \* ARABIC 34 Caching Store Provider Properties Definition

3.       Define the property like this screen shoot

Figure  SEQ Figure \* ARABIC 35 Caching Store Provider Properties

4.       You will see your application configuration file has been updated like this

<?xml version="1.0" encoding="utf-8"?>

<configuration>

  <configSections>

    <section

      name="securityConfiguration"

     

type="Microsoft.Practices.EnterpriseLibrary.Security.

Configuration.SecuritySettings,

            Microsoft.Practices.EnterpriseLibrary.Security,

            Version=3.1.0.0, C

            ulture=neutral,

            PublicKeyToken=b03f5f7f11d50a3a" />

    <section

      name="dataConfiguration"

     

type="Microsoft.Practices.EnterpriseLibrary.Data.

Configuration.DatabaseSettings,

            Microsoft.Practices.EnterpriseLibrary.Data,

            Version=3.1.0.0,

            Culture=neutral,

            PublicKeyToken=b03f5f7f11d50a3a" />

    <section

      name="cachingConfiguration"

     

type="Microsoft.Practices.EnterpriseLibrary.

Caching.Configuration.CacheManagerSettings,

            Microsoft.Practices.EnterpriseLibrary.Caching,

            Version=3.1.0.0,

            Culture=neutral,

            PublicKeyToken=b03f5f7f11d50a3a" />

  </configSections>

  <securityConfiguration

    defaultAuthorizationInstance="" defaultSecurityCacheInstance="">

    <authorizationProviders>

      <add

       

type="Microsoft.Practices.EnterpriseLibrary.

Security.AuthorizationRuleProvider,

                  Microsoft.Practices.EnterpriseLibrary.Security,

                  Version=3.1.0.0,

                  Culture=neutral,

                  PublicKeyToken=b03f5f7f11d50a3a"

            name="MyTestRuleProvider">

        <rules>

          <add

            expression="(I:henry OR I:ela) AND R:Manager "

            name="MyTestRule" />

        </rules>

      </add>

    </authorizationProviders>

    <securityCacheProviders>

      <add

        cacheManagerInstanceName="MyCacheManager"

        defaultSlidingSessionExpirationInMinutes="10"

        defaultAbsoluteSessionExpirationInMinutes="60"

        type="Microsoft.Practices.EnterpriseLibrary.

Security.Cache.CachingStore.CachingStoreProvider,

  Microsoft.Practices.EnterpriseLibrary.

Security.Cache.CachingStore,

              Version=3.1.0.0,

              Culture=neutral,

              PublicKeyToken=b03f5f7f11d50a3a"

        name="MyCachingStoreProvider" />

    </securityCacheProviders>

  </securityConfiguration>

  <cachingConfiguration

    defaultCacheManager="MyCacheManager">

    <cacheManagers>

      <add

        expirationPollFrequencyInSeconds="60"

        maximumElementsInCacheBeforeScavenging="1000"

        numberToRemoveWhenScavenging="10"

        backingStoreName="Null Storage"

        name="MyCacheManager" />

    </cacheManagers>

    <backingStores>

      <add

        encryptionProviderName=""

        type="Microsoft.Practices.EnterpriseLibrary.

Caching.BackingStoreImplementations.NullBackingStore,

              Microsoft.Practices.EnterpriseLibrary.Caching,

              Version=3.1.0.0,

              Culture=neutral,

              PublicKeyToken=b03f5f7f11d50a3a"

        name="Null Storage" />

    </backingStores>

  </cachingConfiguration>

</configuration>

5.       Let’s create code to demonstrate the Cache Store Provider.

using System;

using System.Collections.Generic;

using System.Text;

 

using System.Security.Principal;

using Microsoft.Practices.EnterpriseLibrary.Security;

 

namespace UsingSecurityApplicationBlock

{

    class Program

    {

        private static IToken _token;

 

        static void Main(string[] args)

        {

            //TestAuthorization();

           

 

            IIdentity identity = new GenericIdentity("henry");

            Console.WriteLine("Saving the identity object to cache");

            _token = SaveIdentity(identity);

            Console.WriteLine(

"This is the token value from identity object : {0}", _token.Value);

 

            Console.WriteLine("Load indetity object : {0}", identity.Name);

            identity = GetIdentity(_token);

            Console.WriteLine(

                "This information from identity Name : {0}, IsAutenticate :

{1}, AuthenticationType : {2}",

                identity.Name,

                identity.IsAuthenticated.ToString(),

                identity.AuthenticationType);

 

            Console.WriteLine("Press any key to exit!");

            Console.ReadLine();

 

 

        }

 

        public static IToken SaveIdentity(IIdentity identity)

        {

            // Create Security Cache Provider

            ISecurityCacheProvider cacheProvider =

                SecurityCacheFactory.GetSecurityCacheProvider(

"MyCachingStoreProvider");

 

            // Get token from identity object

            IToken token = cacheProvider.SaveIdentity(identity);

           

            return token;

        }

 

        public static IIdentity GetIdentity(IToken token)

        {

            // Create Security Cache Provider

            ISecurityCacheProvider cacheProvider =

                SecurityCacheFactory.GetSecurityCacheProvider(

"MyCachingStoreProvider");

 

            IIdentity identity = null;

 

            if (token != null)

                identity = cacheProvider.GetIdentity(token);

 

            return identity;

        }

 

        public static void TestAuthorization()

        {

            IPrincipal principle = new GenericPrincipal(

                new GenericIdentity("henry"), new string[] { "Manager" });

 

            IAuthorizationProvider provider =

                AuthorizationFactory.GetAuthorizationProvider(

"MyTestRuleProvider");

            bool authorized = provider.Authorize(principle, "MyTestRule");

 

            if (authorized)

                Console.WriteLine("You are authorized to use this...");

            else

                Console.WriteLine("You are not authorized to use this...");

 

            Console.WriteLine("Press any key to exit!");

            Console.ReadLine();

        }

    }

}

In the code snippet above we define two static method, first SaveIdentity() require us to pass instance of IIdentity and return IToken object. Token object provide us to snapshot of current information that want to retrieve from cache. This token has property “Name”. That has type of string. It’s represent a GUID. The second static method is to retrieve identity from cache using existing token.

Finally {}

We have been seen that Security Application Block provides us with Authentication and Security Cache Strategy that easy to implement and could be extend based on your requirement. My suggestion is take some benefit from them and if you are less time to manage your security in your application, this solution could reduce your amount of time to developing security library in your code.

Share this post: | | | |
Pattern Adoption

 

Gregg Irwin said this about pattern adoption:

"For me, many concepts, like patterns, are learned in stages":

  1. You use it without being aware that you're using it
  2. You hear about it, read up on it, and tinker a bit
  3. You learn more and start using it explicitly, if naïvely
  4. You get the fire and evangelize (optional)
  5. Something "clicks"
  6. You learn more and apply it "less naïvely" and more implicitly
  7. Time passes and you see flaws
  8. You question the concept (often because you misapplied it)
  9. You either forget about it or add knowledge and experience (Repeat steps 59 as necessary)
  10. You use it without being aware that you're using it"
Share this post: | | | |
Good Object Oriented Design Principles:

Robert C. Martin's Principles...

-          Single Responsibility Principle (SRP)

An item such as a class should just have one responsibility and solve that responsibility well. If a class is responsible both for presentation and data access, that's a good example of a class breaking SRP.

-          Open-Closed Principles (OCP)

A class should be closed for modification, but open for extension. When you change a class, there is always a risk that you will break something. But if instead of modifying the class you extend it with a sub-class, that's a less risky change.

-          Liskov Substitution Principle (LSP)

Assume that you have an inheritance hierarchy with Person and Student. Wherever you can use Person, you should also be able to use a Student, because Student is a subclass of Person. At first this might sound like that's always the case automatically, but when you start thinking about reflection (reflection is a technique for being able to programmatically inspect the type of an instance and read and set its properties and fields and call its methods, without knowing about the type beforehand), for example, it's not so obvious anymore. A method that uses reflection for dealing with Person might not expect Student.

The reflection problem is a syntactical one. Martin uses a more semantical example of Square that is a Rectangle. But when you use SetWidth() for the Square, that doesn't make sense, or at least you have to internally call SetHeight() as well. A pretty different behavior from what Rectangle needs.

 

Share this post: | | | |
Ten Must-Have Tools Every Developer Should Download Now

Ten Must-Have Tools Every Developer Should Download Now

  • NUnit to write unit tests
  • NDoc to create code documentation
  • NAnt to build your solutions
  • CodeSmith to generate code
  • FxCop to police your code
  • Snippet Compiler to compile small bits of code
  • Two different switcher tools, the ASP.NET Version Switcher and the Visual Studio .NET Project Converter
  • Regulator to build regular expressions
  • .NET Reflector to examine assemblies

Supported Links:

Share this post: | | | |
Exploring Validation Application Block

Exploring Validation Application Block

(feel sory if the picture is could not show, i have been write this in ms word. i have enclose a zip for it) 

Validation Application Block from Enterprise Library 3.1 provide library of classes, called validators, that supplies code for validating .Net Framework data types. The validating processes in application have many forms. It could validate the input from user or system.

The library support aggregate validator like AndCompositeValidator and OrCompositeValidator. AndCompositeValidator use the logical "And" to perform validation, all validators in the composite must evaluate true to produce valid validation otherwise would perform false. OrCompositeValidator on the other hand perform validation using logical "Or", if once of the validator in the composite evaluated true, it will produce valid validation.

We could group validator together in a rule set. We use rule set to validate complex object or graph.

There are three setting strategy to perform validation using Validation Application Block:

1.       Using Configuration

2.       Using .NET Attributes

3.       Using Code

Preparing Application for Using Validation Application Block

There are several assemblies from Enterprise Library that should be reference by the application.

1.       Microsoft.Practice.EnterpriseLibrary.Validation.dll

This is the core library for Validation Application Block.

2.       Microsoft.Practices.EnterpriseLibrary.Common.dll

3.       Microsoft.Practices.ObjectBuilder.dll

If we are using Validation Application Block Integration we could reference these assemblies for each application type:

a)      Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WinForms.dll

Use this assembly for integrating Validation Application Block to Desktop Application.

b)      Microsoft.Practices.EnterpriseLibrary.Validation.Integration.AspNet.dll

Use this assembly for integrating Validation Application Block to Web Application.

c)       Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF.dll

Use this assembly for integrating Validation Application Block to WCF Application.

Set Import/Using statement to reference Namespace.

using Microsoft.Practices.EnterpriseLibrary.Validation;

using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

Setting Application Configuration

First you must have Application Configuration File such as app.config or web.config.

Figure SEQ Figure \* ARABIC 4   Edit Enterprise Library Configuration

Edit the Config file using Enterprise Library Configuration. You could perform this by right click the configuration and point to Edit Enterprise Library Configuration like picture above. Visual Studio will show Enterprise Library Configuration Pane like this below.

 

Figure SEQ Figure \* ARABIC 5   Enterprise Library Configuration Pane

To create Validation Application Configuration select the Application Configuration file and create New Validation Application Block. This action will add Validation Application Block configuration to your application configuration file.

 

Figure SEQ Figure \* ARABIC 6   Creating New Validation Application Block

The configuration could use protection level:

1.       RsaProtectedConfigurationProvider

2.       DataProtectionConfigurationProvider

 

Figure SEQ Figure \* ARABIC 7   Configuration Protection Level

 

Figure SEQ Figure \* ARABIC 8   Result of Application Configuration File after add Validation Application Block Configuration

After finishing edit the application configuration you could see the result just like picture above.

The configuration schema use Microsoft.Practices.EnterpriseLibrary.Validation.Configuration.ValidationSettings type to handler the validation schema. This handler define validation element (required). validation element have several child elements

1.       EncryptedData Element

This element is define the protection level for the configuration file. This element has attribute "xmlns" to define namespace of the EncryptedData element.

2.       type Element

This element define type that will be validated. This element have several attributes:

o   assemblyName

The assembly name that contain the type

o   defaultRuleset

The default Ruleset

o   name

The name of the type to be validated

The type element has child element "ruleset" element, it has "name" attribute that is the name of the rule set.

There are other element like methods, fields, properties and validator. Please refer the documentation to see the details.

Using Validation Application Block

There are several ways to apply the validation in your application. Let's see each scenario with some samples.

Suppose we would like to validate for each members of concrete class. I choose Customer class for this scenario. This scenario check property Name for validate the input length. 

using System;

using System.Collections.Generic;

using System.Text;

 

using Microsoft.Practices.EnterpriseLibrary.Validation;

using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;

 

namespace UsingValidationApplicationBlock

{

    public class Customer

    {

        int _id;

        string _name;

        string _address;

 

        public Customer(int id, string name, string address)

        {

            this._id = id;

            this._name = name;

            this._address = address;

        }

 

        public int Id

        {

            get { return _id; }

            set { _id = value; }

        }

 

        [StringLengthValidator(1,50,Ruleset="StringRuleset",

            MessageTemplate="Name must be between 1 to 50 characters")]

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

 

        public string Address

        {

            get { return _address; }

            set { _address = value; }

        }

 

    }

}

In code above we applying StringLengthValidator from Microsoft.Practices.EnterpriseLibrary.Validation.Validators.StringLengthValidatorAttribute

This attribute have several parameters:

1.       LowerBound

This will check the lower bound for the string input value.

2.       UpperBound

This will check the upper bound for the string input value.

3.        Named Parameters

These define several parameter arrays like Ruleset, MessageTemplate, Tag, and Negate.

If you use this class and set the Name property with value, the validator will check the property with the attribute that you set for the property.

The Interesting One Self Validation

Self Validation is a scenario for validating the application that use capabilities of validator to invoke logic to perform validation. The class that wants to perform this must mark with HasSelfValidation attribute. And the logic for validation must mark with SelfValidation attribute. There are several rule that must follow for using this scenario:

1.       The Validation Logic must have instance parameter with ValidationResults as the type, and only should have this parameter only. The logic also must not return any value (void). After performing validation the logic must update ValidationResults instance if the validation fails.

2.       Self Validation could perform in the derived class. To perform this the base and derive class must applying HasSelfValidation attribute. And the logic that performs self validation must have public access.

Self Validation logic invokes when Validation.Validate method is called.

Samples of using Self Validation, this code snippet has logic DoValidate.

    [HasSelfValidation]

    public class Address

    {

        private string _zipCode;

        [StringLengthValidator(1, 10,

        MessageTemplate = "ZipCode Invalid Length")]

        public string ZipCode

        {

            get { return _zipCode; }

            set { _zipCode = value; }

        }

        [SelfValidation]

        public void DoValidate(ValidationResults results)

        {

            ValidationResult result = new ValidationResult

                     ("Error Message", typeof(Address), "", "", null);

            ValidationResult result2 = new ValidationResult

                     ("Error Message2", typeof(Address), "", "", null);

            results.AddResult(result);

            results.AddResult(result2);

        }

    }

 

Figure SEQ Figure \* ARABIC 9   SelfValidationAttribute

Deep into Validator Class

Let's go into the core of Validation Class.

 

Figure SEQ Figure \* ARABIC 10 Validator Class Diagram

In Validator abstract class we could see two overload signatures of "Validate". First method takes object as parameter and return "ValidationResult".  The second required object and instance ValidationResults. The Validator also define three properties, "MessageTemplate" and "Tag" are public properties and "DefaultMessageTemplate" is protected abstract property. MessageTemplate property is for defining message that will be used when creating a ValidatioResult object is created. The Tag property is to filter validation result.

 

Figure SEQ Figure \* ARABIC 11 ValidatioResult Class

"ValidationResult" class is object that holds information when Validator object determine that a rule is violated. The Validator will create collection of ValidationResult call "ValidationResults". To define data we could pass parameters to the constructors of ValidationResult class, then the user of this class could return the information via read only properties.

 

Figure SEQ Figure \* ARABIC 12 ValidationResults Collection Class for ValidationResult

In the signature class of ValidationResults class we could see that we could add ValidationResult using "AddResult" method. Also we could add another ValidationResults too using "AddAllResults" method.

 

Figure SEQ Figure \* ARABIC 13 ValidationFactory class

Enterprise Library also provides "ValidationFactory" class that support for creating Validator instance. This class has many public static interfaces that return Validator instance.

 

Figure SEQ Figure \* ARABIC 14 Validation Class

One more think you may use is Enterprise Library Validation Application Block already define "Façade Service" that could make easy to return ValidatioResults. This static class name is "Validation".

To summaries above class these are base class that should see if you want to extend those classes.

-          Microsoft.Practices.EnterpriseLibrary.Validation.Validator

-          Microsoft.Practices.EnterpriseLibrary.Validation.Validator<T>

-          Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResult

-          Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResults

-          Microsoft.Practices.EnterpriseLibrary.Validation.ValidationFactory

-          Microsoft.Practices.EnterpriseLibrary.Validation.Validation

Limitation of Attribute-Based Validation

There are some limitation or rule that must follow if you implement attribute-based validation. This table shows you the summary of attribute-based validation.

Target Type

Behavior

Class

Only  NonNullValidator, ObjectCollectionValidator, and Composite Validator could use in class level.

Field

The value of the field is validated.

Property

Only the value of get will be validated.

Method

Only Validate the return value of the method, and the method must not have parameter.

Parameter

This could only happen when implementing Policy Injection Application Block

Figure SEQ Figure \* ARABIC 15 Attribute-Based Validation Rule

Try { Validator } catch { Your Understanding}

To see how each Validator could perform validation let's see with sample for each Validator in action.

ObjectValidator and ObjectCollectionValidator

 

Figure SEQ Figure \* ARABIC 16 ObjectValidator and ObjectCollectionValidator Base class

"ObjectValidator" purpose is to validate any type that you specify. In the sample we have Customer and Order objects, the Order object hold reference Customer Object, we want to validate the Customer via ObjectValidator. If the Validator.Validate() is called it will check the rule for Customer object.

public class Customer

    {

        private string _name;

 

        [StringLengthValidator(1, 200, MessageTemplate =

"Customer must have Name between 1 to 200 characters")]

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

    }

 

    public class Order

    {

        private Customer _customer;

 

        [ObjectValidator(MessageTemplate = "Math is not valid")]

        public Customer Customer

        {

            get { return _customer; }

            set { _customer = value; }

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            Order order = new Order();

            order.Customer = new Customer();

 

            Validator<Order> validator =

                  ValidationFactory.CreateValidator<Order>();

            ValidationResults results = validator.Validate(order);

 

            if (!results.IsValid)

                foreach (ValidationResult result in results)

                {

                    Console.WriteLine(result.Message);

                }

            Console.WriteLine("Press any key to exit!");

            Console.ReadLine();

        }

    }

 

Figure SEQ Figure \* ARABIC 17 Console Result

ObjectCollectionValidator is like objectValidator but will validate collection object.

public class Customer

    {

        private string _name;

 

        [StringLengthValidator(1, 200,

MessageTemplate =

"Customer must have Name between 1 to 200 characters")]

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

    }

 

    public class Order

    {

        private Customer _customer;

 

        private ArrayList _items = new ArrayList();

 

        [ObjectCollectionValidator(typeof(Item))]

        public ArrayList Items

        {

            get { return _items; }

            set { _items = value; }

        }

 

        public void AddItems(Item item)

        {

            Items.Add(item);

        }

 

        [RangeValidator(

            0,

            RangeBoundaryType.Exclusive,

            0,RangeBoundaryType.Ignore,

            MessageTemplate="Quantity must not be zero")]

        public int Quantity()

        {

            return Items.Count;

        }

 

        [ObjectValidator(MessageTemplate = "Math is not valid")]

        public Customer Customer

        {

            get { return _customer; }

            set { _customer = value; }

        }

    }

 

    [NotNullValidator(MessageTemplate="Item could not be null")]

    public class Item

    {

        private string _itemName;

 

        [StringLengthValidator(1,5,

MessageTemplate="Item must have Name between 1 to 5 characters")]

        public string ItemName

        {

            get { return _itemName; }

            set { _itemName = value; }

        }

    }

 

    class Program

    {

        static void Main(string[] args)

        {

            Order order = new Order();

            order.Customer = new Customer();

            order.Customer.Name = "Henry";

            Item car = new Item();

            car.ItemName = "Car";

            order.AddItems(car);

 

            car = new Item();

            car.ItemName = "Mercedes Benz";

            order.AddItems(car);

 

            Validator<Order> validator =

                  ValidationFactory.CreateValidator<Order>();

            ValidationResults results = validator.Validate(order);

 

            if (!results.IsValid)

                foreach (ValidationResult result in results)

                {

                    Console.WriteLine(result.Message);

                }

            Console.WriteLine("Press any key to exit!");

            Console.ReadLine();

        }

    }

We add the sample with Item object, the Order hold collection (ArrayList) of Item. You see in the code we test to add 2 items first will satisfied and the second will failed because the name is more than 5 characters.

Thing to remember that if ObjectValidator and ObjectCollectionValidator evaluated object that has null reference it will ignore the validation.

Composite Validator

 

Figure SEQ Figure \* ARABIC 18 AndCompositeValidator and OrCompositeValidator

To test AndCompositeValidator we add code in the Customer class like this:

    public class Customer

    {

        private string _name;

 

        [ValidatorComposition(CompositionType.And)]

        [NotNullValidator(MessageTemplate = "Customer could not be null")]

        [StringLengthValidator(1, 200, MessageTemplate =

"Customer must have Name between 1 to 200 characters")]

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

    }

Suppose if we forget to set the Name property the validation will failed.

    class Program

    {

        static void Main(string[] args)

        {

            Order order = new Order();

           

            order.Customer = new Customer();

 

            //order.Customer.Name = "Henry";

            Item car = new Item();

            car.ItemName = "Car";

    ...

 

Figure SEQ Figure \* ARABIC 19 AndCompositeValidator

Customer Name property must satisfy both Validator NotNullValidator and StringlengthValidator to successfully validate.

The OrCompositeValidator also validate multiple Validator object but use the logic or.

Property Comparison Validator

 

Figure SEQ Figure \* ARABIC 20 PropertyComparisonValidator hierarchy

Purpose of this Validator is to check value of property with another property.

To illustrate this Validator add MaxQuantity property in the order class and set it to return 1. Use PropertyComparisionValidator to compare with Quantity Property. If the Order Item Quantity have value Greater than MaxQuantity of then the validation will failed.

public class Order

    {

        private Customer _customer;

               

        private ArrayList _items = new ArrayList();

 

        private int _maxQuantity = 1;

 

        [ObjectCollectionValidator(typeof(Item))]

        public ArrayList Items

        {

            get { return _items; }

            set { _items = value; }

        }

 

        public void AddItems(Item item)

        {

            Items.Add(item);

        }

 

        [PropertyComparisonValidator(

           "Quantity",

            ComparisonOperator.GreaterThan

            ,MessageTemplate=

"Quantity must not not higher than Max Quantity")]

        public int MaxQuantity

        {

            get { return _maxQuantity; }

        }

 

        [RangeValidator(

            0,

            RangeBoundaryType.Exclusive,

            0, RangeBoundaryType.Ignore,

            MessageTemplate = "Quantity must not be zero")]

        public int Quantity

        {

            get { return Items.Count; }

        }

 

        [ObjectValidator(MessageTemplate = "Math is not valid")]

        public Customer Customer

        {

            get { return _customer; }

            set { _customer = value; }

        }

    }

Defining Rule Set Validation Using Application Configuration File

You could set the Rule Set via Attribute or Application Configuration File (app.config or web.config). I will show you how to configure Rule Set using application configuration file.

Enterprise Library provides us to configure Validation Application Block Rule Set via configuration, I already tell you how in above section how to configure your application configuration file. In this demo we will add Rule Set for Customer Type. We will be using "DomainValidator". DomainValidator is to check a given value to the Domain Collection Value. These are the steps:

1.       Add Type to Validate

Right click your Validation Application Block and set

Action :: Validation Application Block >> New >> Type

It will populate Type Selector Dialog like this

 

Figure SEQ Figure \* ARABIC 21 Type Selector Dialog

2.       Load your assembly if your assembly doesn't show in the list by click the Load an Assembly... button. Pick the type that you want to add in the Validation Application Block.

3.       Add Rule Set to the type that you pick earlier.

Action :: Type >> New >> Rule Set

Enterprise Library Configuration Editor will add Rule Set object tree like picture below.

 

Figure SEQ Figure \* ARABIC 22 Rule Set Tree

                You could specify the name of the Rule Set.

4.       Specify the Object that you want to apply in the Rule Set.

Action :: Rule Set >> New >> Choose Members

It will populate Member Selector dialog like this

 

Figure SEQ Figure \* ARABIC 23 Member selector dialog

                Select what object that you want to apply to the Rule Set.

5.       We could implement Default Validator from Validation Application Block by right click the field, property, or method in the rule set members.

Action :: Rule Set Member >> New >> Validator List

Depend on the Validator that you have been selected you could set the properties in the Properties Dialog.

 

Figure SEQ Figure \* ARABIC 24 Properties Dialog

Sometime you would like to implement validation to type that you specify in the configuration. You could use self node in the configuration.

Finally you could execute the validation using code like this

            Customer cst = new Customer();

            cst.Name = "Ela";

            Validator<Customer> cVal =

                  ValidationFactory.CreateValidator<Customer>("Test");

            ValidationResults res1 = cVal.Validate(cst);

            if (!res1.IsValid)

                foreach (ValidationResult result1 in res1)

                {

                    Console.WriteLine(result1.Message);

                }

The code snippet above will validate the Customer and use Test Rule Set.

Finally {}

Doing Validation could be frustrated when you have complexity of business rule. With Enterprise Library Validation Application Block you could composed and extend the library to deliver easy and maintainable solution. There is another important Application block that could be used if you implement Validation Application Block, The Policy Injection Application Block. The Policy Injection Application Block provides a mechanism for automatically applying policies to object instances; this helps developers to better manage crosscutting concerns and maximize separation of concerns and encapsulation of behavior.

 

Share this post: | | | |