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.
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.