skip to the main content area of this page
Patterns and Practices

 

Repository Factory and Policy Injection Application Block Doing Validation


The Repository Factory generates interfaces for each repository class in the data access layer which allows one to add call handlers from the Policy Injection Application Block to the interfaces to help with features like caching, validation, etc.

I provided an example of using the Policy Injection Application Block and Validation Application Block with the Repository Factory at the Tampa .NET Developer Group on October 18th, 2007.

In the example, I discussed adding a Restaurant to a backend database:

 

Repository Factory and Policy Injection Application Block

 

The Restaurant Class is decorated with Validator Attributes that specify a valid restaurant which are used for both validation at the UI level via AJAX using the PropertyProxyValidator and ServerSideValidationExtender, but also when passed as an argument to the RestaurantRepository Class as part of an insert or update to the database.

The Restaurant Class with Validator Attributes are shown below:

 

public partial class Restaurant

{

    public Restaurant()

    {

    }

 

    public Restaurant(System.Int32 cityId, System.String name, System.String phone, System.Int32 restaurantId, System.String url)

    {

        this.cityIdField = cityId;

        this.nameField = name;

        this.phoneField = phone;

        this.restaurantIdField = restaurantId;

        this.urlField = url;

    }

 

    private System.Int32 cityIdField;

 

    public System.Int32 CityId

    {

        get { return this.cityIdField; }

        set { this.cityIdField = value; }

    }

 

    private System.String nameField;

 

    [StringLengthValidator(1, 200, MessageTemplate = "Name must be between {3} - {5} characters.")]

    public System.String Name

    {

        get { return this.nameField; }

        set { this.nameField = value; }

    }

 

    private System.String phoneField;

 

    [StringLengthValidator(1,200,MessageTemplate="Phone number must be between {3} - {5} characters.")]

    [RegexValidator(@"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}", MessageTemplate="Invalid Phone.")]

    public System.String Phone

    {

        get { return this.phoneField; }

        set { this.phoneField = value; }

    }

 

    private System.Int32 restaurantIdField;

 

    public System.Int32 RestaurantId

    {

        get { return this.restaurantIdField; }

        set { this.restaurantIdField = value; }

    }

 

    private System.String urlField;

 

    [StringLengthValidator(1, 200, MessageTemplate = "Url must be between {3} - {5} characters.")]

    [RegexValidator(@"http(s)?://([\w-]+\.)+[\w-]+(/[\w- ./?%&=]*)?", MessageTemplate = "Invalid Url.")]

    public System.String Url

    {

        get { return this.urlField; }

        set { this.urlField = value; }

    }

 

}

 

The RestaurantRepository Interface, IRestaurantRepository, is decorated with Policy Injection Application Block Call Handlers to provide argument validation during insert and update:

 

public interface IRestaurantRepository

{

    List<Restaurant> GetAllFromRestaurant();

 

    List<Restaurant> GetRestaurantByCityId(System.Int32 cityId);

 

    [ValidationCallHandler]

    void Add(Restaurant restaurant);

 

    void Remove(System.Int32 restaurantId);

 

    [ValidationCallHandler]

    void Save(Restaurant restaurant);

}

 

The ValidationCallHandler will invoke the Validation Application Block prior to inserting and updating the restaurant when we properly wrap it as follows:

 

try

{

    IRestaurantRepository repository

        = RepositoryFactory.Create<IRestaurantRepository>();

    IRestaurantRepository wrappedRepository

        = PolicyInjection.Wrap<IRestaurantRepository>(repository);

    wrappedRepository.Add(restaurant);

}

catch (ArgumentValidationException ex)

{

    string error = string.Empty;

    foreach (ValidationResult result in ex.ValidationResults)

        error += result.Message + ".  ";

}

catch (RepositoryException ex)

{

    //Do Sommething... Error saving to the database...

}

 

If a validation error occurs, the ArgumentValidationException is thrown and provides all the broken rules associated with the Restaurant Class. If a database related error occurs, the Repository Factory throws a typed exception that derives from RepositoryException.

One could modify the code to the RepositoryFactory Class and have it internally call PolicyInjection.Wrap if one did not want to make a separate call.

The combination of the new Repository Factory Interfaces, Policy Injection Application Block, ValidationCallHandler Attribute, PropertyProxyValidator, and ServerSideValidationExtender provide some wonderful end-to-end validation in your web applications.


Tags: PolicyInjectionApplicationBlock, ValidationApplicationBlock, ValidationCallHandler, ArgumentValidationException


Topics



 

Popular Tags



Recent Links