Introducción al Validation Application Block

por Maxi Guillén - Daniel Laco  27. diciembre 2007

 

Enterprise Library Validation Application Block

Uno de los temas siempre mas controversiales en del desarrollo, es el proceso de validación, ya sea en al entrada de datos, en el manejo de las reglas de negocio o en la parte de persistencia de los datos.

Con el Validation Application Block (VAP) contenido en la Enterprise Library podemos resolver de un modo elegante y personalizable toda la problemática de validación en nuestras aplicaciones.

El VAP brinda un entorno común para definir reglas de validación para los objetos del negocio e interfaces de usuario. Facilita varios tipos de clases de validadores que incluyen código para validar tipos de datos de .net. Y pueden desarrollarse validadores personalizados para reutilizar.

Se pueden crear grupos de validadores llamados Rule Set (1 a N validators) mediante parámetros de atributos. Es una forma de validar objetos complejos agrupando validadores de diferentes tipos y aplicándolos a campos, propiedades y a nested objects.

Las validaciones se pueden definir o bien a nivel de atributos en las clases o en un archivo de configuración.


Se puede utilizar con las siguientes tecnologías:
ASP .NET
Windows Forms
Ajax
WCF
WPF Requerimientos:
.Net Framework 2, 3 o 3.5

Para utilizar ValidationBlock no es necesario referenciar toda la Enterpise Library, sólo debemos referenciar las siguientes bibliotecas:
Microsoft.Practices.EnterpriseLibrary.Comon.dll
Microsoft.Practices.EnterpriseLibrary.Validation
Microsoft.Practices.ObjectBuilder.dll
Microsoft.Practices.EnterpriseLibrary.Integration.WinForms (solo en la capa de presentación)

Se utilizan los siguientes name space:
using Microsoft.Practices.EnterpriseLibrary.Validation;
using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;
using Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WinForms; (solo en la capa de presentación)

Validadores predefinidos
Validation Application Block incluye un conjunto de validadores predefinidos que comúnmente se pueden utilizar en las aplicaciones. Cada validador está asociado a un tipo específico. Algunos de estos validadores son:

  • ContainsCharacterValidator
  • NotNullValidator
  • ObjectValidator
  • DomainValidator
  • StringLengthValidator
Ejemplo de utilización de atributos:
public class Customer
{
    // validator attributes with field as target
    [NotNullValidator]
    [StringLengthValidator(1, 50)]
    public string Name;
 
    // validator attribute with property as target
    [DateRangeValidator("2007-10-27T00:00:00", "2008-10-27T00:00:00")]
    public DateTime DateJoined { get { return this.dateJoined; } }
    
    // validator attribute with method as target
    // assume that ShippingAddress is defined elsewhere and has validation
    [ObjectValidator]
    public ShippingAddress GetPrimaryShippingAddress()    {….}
    // validator attribute with method as target (applied to an enumeration)
    [ObjectCollectionValidator(typeof(ShippingAddress))]
    public IEnumerable<ShippingAddress> GetAlternateShippingAddresses()    {….}
}

Validadores compuestos Se pueden crear Validadores compuestos AND u OR (AndCompositeValidator y OrCompositeValidator), agrupa validaciones en forma lógica, es decir en el caso de And todos los validadores deben devolver verdadero para que el objeto sea válido. Las formas para crear validadores compuestos son:

  • Usar la herramienta de configuración
  • Usar atributos
  • Mediante código

Ejemplo por código:

Validator validator = new AndCompositeValidator(new NotNullValidator(), new StringLengthValidator(4, 8));
string password = "123";
ValidationResults results = validator.Validate(password);
bool esValido = results.IsValid;


Ejemplo por atributos:

public class cliente
{
    private string nombre;
    [ValidatorComposition(CompositionType.And)]
    [NotNullValidator(MessageTemplate = ValidatorMsgs.NotNullMsg), 
     StringLengthValidator(1, 50, MessageTemplate = ValidatorMsgs.StringRange50)]
    public string Nombre
    {
        Get{ return nombre; }
        Set{ nombre = value }
    }
}


Atributos modificadores de validación

Permiten modificar el comportamiento de los atributos de validación. Los atributos modificadores son:

  • ValidatorComposition = [CompositionType.And/CompositionType.Or], permite hacer override del comportamiento por defecto (AND) cuando hay más de un atributo de validación.
  • IgnoreNulls, los demás validadores no serán llamados si el valor que se está verificando es nulo.


Propiedades de los atributos de validación

Property name Description
MessageTemplate Descripcion que aparecerá en la propiedad Message del resultado, si se integra con winforms es lo mostrará el ErrorProvider en la intefaz de usuario.
MessageTemplateResourceName This property defines the name of the resource for message templates.
MessageTemplateResourceType This property defines the name of the type used for the message template resource.
Negate Modifica el comportamiento del validador para que falle la validación si se cumple la condición. Al contrario del comportamiento común que consiste en fallar la validación si no se cumple la condición
Tag Se usa para permitir clasificar los resultados
Ruleset Nombre de la regla a la que pertenece el validador


Ejemplo de uso con una clase:

public partial class Estacion : IDisposable
{
    private int _idEstacion;
    private string _nombre;
        private string _ubicacion;
    private string _telefono;
    private IList<OperacionCabina> _operacionCabinaList;
 
    public int IdEstacion
    {
        get { return this._idEstacion; }
    }
 
    [NotNullValidator(MessageTemplate = ValidatorMsgs.NotNullMsg), 
    StringLengthValidator(1, 50, MessageTemplate = ValidatorMsgs.StringRange50)]
    public string Nombre
    {
        get { return this._nombre; }
        set
        {
            this._nombre = value; 
        }
    }…
 


Validación Self
Consiste en implementar la lógica de validación dentro de la misma clase. Se rotula la clase con [HasSelfValidation] y con [SelfValidation] a cada método de la clase que se llamará cuando se efectúe la validación.

Por ejemplo:

[HasSelfValidation]
public class TemperatureRange
{ 
    private int min; 
    private int max;
 
    // ...
 
    [SelfValidation]             
    public void CheckTemperature(ValidationResults results) 
    { 
         if (max < min) 
           results.AddResult(new ValidationResult("Max less than min", this, null, null, null));
    } 
} 


Si se quiere que la validación sea heredable hay que marcar con HasSelfValidation tanto a la clase padre como a sus hijos y el método de validación debe ser público.


Validación de objetos

Puede realizarse mediante un llamado al método Validate de la clase estática Validation, el resultado se obtiene mediante la clase ValidationResults

Ejemplo de validación de una instancia de la clase Estacion:

Estacion estacion = Global.Data.GetObject<Estacion>();
Validation results = Validation.Validate(estacion);
Bool esValido = results.IsValid;


Puede utilizarse también la clase ValidationFactory para crear una instancia del validador.

Customer myCustomer = new Customer( /* ... */ );
Validator<Customer> goldCustomerValidator =   ValidationFactory.CreateValidator<Customer>("GoldCustomer");
ValidationResults results = goldCustomerValidator.Validate(myCustomer);


Resultados de una validación

El método de validación retornará el resultado en una instancia de la clase ValidationResults que es una colección de objetos ValidationResult los cuales tienen las siguientes propiedades:

Property

Description

Key

Nombre que identifica la ubicación del validador. Ej:”Nombre” significa que se colocó un validador en la propiedad nombre de un objeto Cliente.

Object

Puntero al objeto que fue validado

Message

Describe la falla de la validación

Tag

Valor ingresado por código que describe el resultado, se utilize para clasificar o filtrar

Target

Validador que falló



Herencia

Las reglas de validación se aplican a través de la jerarquía de clases. Si una clase hereda un miembro de de otra y no lo sobrecarga se aplican los validadores de la clase de la cual hereda. Si una clase hereda un miembro y lo sobrecarga, entonces no se aplican las validaciones especificadas en la clase de la cual hereda.

Crear un nuevo validador

Se pueden crear clases validadoras, pueden validar tipos de datos de nuevas formas o pueden validar datos complejos como instancias de la clase Cliente.

Para esto se puede heredar de las clases:

  • Validator<T>, para crear validadores fuertemente tipados.
  • Validator

Crear un nuevo atributo perzonalizado

Se pueden crear atributos personalizados heredando de la clase ValidatorAttribute.

Integración con WinForms
Validation Application Block tiene la capacidad de trabajar en conjunto con el objeto ErrorProvider para mostrar el resultado de las validaciones directamente en los controles con el clásico ícono rojo.
Esto se realiza soltando un control ErrorProvider en el Form deseado y luego soltando un control ValidatorProvider (Que debe ser obtenido partir de la biblioteca de Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WinForms.
Cada control ValidatorProvider que se suelte sobre el formulario adiciona 3 nuevas propiedades para cada control del formulario que pueden ser accedidas desde la grilla de propiedades. Estas propiedades son: PerformValidation, SourcePropertyName y ValidatedProperty.
Para que el formulario valide automáticamente los controles debemos efectuar los siguientes pasos:

  1.  
    1. ErrorProvider: seleccionar el control ErrorProvider deseado del formulario.
    2. Enabled: debe ser igual a True
    3. RulesetName: debe ser igual a la regla deseada si no se utilizó este parámetro en los atributos se puede dejar vacío.
    4. SourceTypeName: Se especifica el camino de namespace hasta la clase contiene las validaciones seguido por el nombre de la biblioteca donde se encuentre.
    5. Ej: SourceTypeName = Entidades.Cliente, Entidades
    6. SpecificationSource: declara desde donde se obtienen las reglas de validación, puede ser desde atributos, archivo de configuración o ambos.
    1. PerformValidation: boleano, true para que el control sea validado con el ErrorProvider.
    2. SourcePropertyName: nombre del campo que tiene definida una validación. Ej. SourcePropertyName=Nombre, si definimos por ejemplo una validación mediante el atributo [NotNullValidator] en la propiedad Nombre de la clase Cliente
    3. ValidatedProperty: nombre de la propiedad del control desde la cual se obtendrá el valor para efectuar la validación. Por ejemplo si el control fuera un TextBox usaríamos ValidatedProperty = Text.
  2. 1. Configurar las propiedades del Control ErrorProvider: 2. Configurar las siguientes propiedades de los controles que se deseen que participen de las validaciones:


Ejemplo de una clase Validator y una clase ValidatorAttribute Personalizado

 [ConfigurationElementType(typeof(CustomValidatorData))]
 public class PercentageValidator: Validator<decimal>
 {
        public PercentageValidator(NameValueCollection attributes) : base(null, null)
        {
        }
 
        public PercentageValidator() : this(null)
        {
        }
 
        protected override void DoValidate(decimal objectToValidate, object currentTarget, 
        string key, ValidationResults validationResults)
        {
            if (objectToValidate < 0 || objectToValidate > 100)
            {
                validationResults.AddResult(new 
                 ValidationResult("El valor debe estar entre 0 y 100.", currentTarget, "Decimal", "", this));
            }
        }
 
        protected override string DefaultMessageTemplate
        {
            get { return "Valor inválido"; }
        }
 }
 
 public class PercentageValidatorAttribute : ValidatorAttribute
 {
        public PercentageValidatorAttribute()
        {
        }
 
        protected override Validator DoCreateValidator(Type targetType)
        {
            return new PercentageValidator();
        }
 }
 
 public class ObjetoTest
 {
        private string nombre;
        private decimal valor;
 
        [PercentageValidator()] //Mi Custom Validator
        public decimal Valor
        {
            get { return valor; }
            set { valor = value; }
        }
 
        [NotNullValidator,StringLengthValidator(1,50)]
        public string Nombre
        {
            get { return nombre; }
            set { nombre = value; }
        }
 }


Como se dijo anteriormente, Application Validation Block permite manejar las reglas de validación mediante el archivo de configuración. El archivo puede ser editado mediante la herramienta “Edit Enterprise Library Configuration”, por ejemplo agregamos una sección de Validation Block y luego se selecciona las clases a validar a partir de ensamblados. Especificamos para cada clase los miembros que serán validados y seleccionamos los Validators deseados y especificamos sus parámetros. También podemos especificar las clases que usen SelfValidation.


Este es un ejemplo de un archivo de configuración, con la definición de validaciones.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="validation" type="Microsoft.Practices./>
      EnterpriseLibrary.Validation.Configuration.
      ValidationSettings,
      Microsoft.Practices.EnterpriseLibrary.Validation"
  </configSections>
  <validation>
    <type name="EntLib3.Subscriber" defaultRule="default">
      <rule name="default">
        <properties>
          <property name="Name">
            <add name="NameNotNull" type="Microsoft.Practices. />
                 EnterpriseLibrary.
                 Validation.Validators.NotNullValidator,
                 Microsoft.Practices.
                 EnterpriseLibrary.Validation"
            <add name="NameLength" type="Microsoft.Practices.
                 EnterpriseLibrary.
                 Validation.Validators.StringLengthValidator,
                 Microsoft.
                 Practices.EnterpriseLibrary.Validation"
                 lowerBound="1"
                 upperBound="200" lowerBoundType="Inclusive"
                 upperBoundType="Inclusive"/>
          </property>
          <property name="EmailAddress">
            <add name="EmailAddressNotNull" type="Microsoft. />
                Practices.
                 EnterpriseLibrary.Validation.Validators.
                 NotNullValidator,
                 Microsoft.Practices.EnterpriseLibrary.
                 Validation"
            <add name="EmailAddressLength" type="Microsoft.
                 Practices.
                 EnterpriseLibrary.Validation.Validators.
                 StringLengthValidator,
                 Microsoft.Practices.EnterpriseLibrary.
                 Validation"
                 lowerBound="1"
                 upperBound="200" lowerBoundType="Inclusive"
                 upperBoundType="Inclusive"/>
          </property>          
        </properties>
      </rule>
    </type>
  </validation>
</configuration>

 

 

Tags: ,

.NET

Acerca de los Autores

Este es el blog del equipo de VEMN SA 
Presentaremos temas que nos parezcan de interés sobre tecnología .NET, Procesos y Metodologías y todo aquello relacionado con el proceso de desarrollo de Software

Month List

BlogRoll

Download OPML file OPML