Sunteți pe pagina 1din 9

ej.

css Buscar

 Login | Registro

DesarrolloWeb.com > Manuales > Manual del framework ASP.NET MVC

Validaciones propias en ASP.NET MVC


Por Eduard Tomàs Seguir a @eixim enis

 24 de enero de 2012  1 Comentarios  .NET

Como crear validaciones propias en ASP.NET MVC tanto en servidor


como en cliente.
En el artículo anterior vimos cómo usar Data
Annotations para crear validaciones y como usar
los helpers para mostrar los mensajes de errores
de las validaciones fallidas. Pero nos quedó en el
tintero ver cómo podemos crear nuestras propias
validaciones, si las que vienen de serie no nos
sirven. Eso es lo que vamos a ver en este artículo.
Atributos de validación propios
La manera en que podemos extender Data
Annotations para validaciones personalizadas es
creando un atributo de validación propio, que
luego podremos aplicar a las propiedades de nuestro viewmodel que queramos validar.
Para crear un atributo de validación propio basta con derivar de la clase ValidationAttribute y por lo
general redefinir un solo método: IsValid. Dicho método recibe un object con el valor a validar y debe
devolver un booleano indicando si la validación ha sido correcta o no:

[AttributeUsage(AttributeTargets.Property)]
public class NumeroParAttribute : ValidationAttribute
{
{
public override bool IsValid(object value)
{
try
{
var number = Convert.ToInt32(value);
return number % 2 == 0;
}
catch (Exception)
{
return base.IsValid(value);
}
}
}

El atributo AtributeUsage se usa para indicarle a .NET donde es válido aplicar este atributo (esto es
siempre que se creen atributos, ya sean para validaciones o para cualquier otra tarea). Aquí estamos
indicando que este atributo se aplica a propiedades, no a métodos o a parámetros.

Una vez creado el atributo su uso es como cualquiera de los que vienen de serie: basta con aplicarlo a
las propiedades que deseemos validar.

public class DemoModel


{
[Range(1, 100, ErrorMessage = "Positivo menor que 100")]
[NumeroPar(ErrorMessage = "El número debe ser par.")]
public int ValorPar { get; set; }
}

Al derivar de la clase ValidationAttribute ya obtenemos la propiedad ErrorMessage que vimos en el


artículo anterior y que nos permite especificar un mensaje de error a mostrar en caso de que la
validación sea fallida. También podemos observar como a pesar de que la clase que hemos creado se
llama NumeroParAttribute para aplicarla basta con decorar la propiedad del viewmodel con
[NumeroPar] (sin el sufijo Attribute).

Ahora podríamos crear una vista para crear objetos DemoModel:

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>DemoModel</legend>

<div class="editor-label">
@Html.LabelFor(model => model.ValorPar)
@Html.LabelFor(model => model.ValorPar)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ValorPar)
@Html.ValidationMessageFor(model => model.ValorPar)
</div>

<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}

Y podríamos comprobar como en efecto tan solo podemos entrar números pares, comprendidos entre 1
y 100:

Figura 1: Validación de número par fallida


Validación propia en cliente
La diferencia del atributo NumeroPar con los que vienen de serie, como p.ej. Range es que
los segundos validan en cliente antes de que se envíen los datos al servidor, mientras que
los atributos propios tan solo se validan en servidor (los atributos que vienen de serie
también se validan en servidor, recordad que los datos deben validarse siempre en servidor
y que la validación en cliente es solo por usabilidad y no por seguridad).
Por supuesto podemos añadir validación en cliente para nuestros atributos. Llegados a este punto debo
decir que el mecanismo exacto depende de la librería de validación que se use en cliente. Aquí vamos a
ver cómo hacerlo usando jQuery Validate que es la librería que se incluye por defecto en ASP.NET MVC.
Para usar otras librerías de validación en cliente sería necesario realizar otros pasos.

Añadiendo el código javascript


Lo primero que debemos hacer es crear el código javascript que va a validar los datos. Si
usamos jQuery Validate esto equivale a añadir un validador nuevo. Para añadir un validador
nuevo basta con darle un nombre y el método javascript a ejecutar:
$.validator.addMethod("numeropar", function (value, element, param) {
return value % 2 == 0;
});
Hemos añadido un validador llamado "numeropar" con la función de validación asociada. Con esto
ahora jQuery Validate sabe que debe llamar a este método javascript cuando se requiera usar el
validador "numeropar".

El siguiente paso es informar a jQuery Validate cuando debe llamar a este validador "numeropar" que
hemos añadido. Para ello necesitaremos código en cliente y en servidor.

La interfaz IClientValidatable
Empecemos por el código de servidor: nuestro atributo de validación debe implementar una
interfaz llamada IClientValidatable. Esta interfaz requiere que implementemos un solo
método llamado GetClientValidationRules, que debe devolver una colección de objetos de la
clase ModelClientValidationRule.
La clase ModelClientValidationRule contiene el nombre de la regla de validación en cliente a aplicar y el
mensaje de error en caso de que dicha validación falle. En nuestro caso una posible implementación es:

public IEnumerable<ModelClientValidationRule>
GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "numeropar"
};
}

Estamos devolviendo una colección con un solo elemento ModelClientValidationRule. El nombre de la


regla de validación en cliente es numeropar y el mensaje de error es el mismo mensaje que se usa para
la validación en servidor.

Nota: ¿Conoces la palabra clave yield? Esa palabra clave de C# permite devolver colecciones sin necesidad de crear
una clase que implemente la colección (usualmente una List<T>). Para más información te remito al blog de José
Manuel Alarcón donde lo cuenta de forma fenomenal:
http://www.jasoft.org/Blog/post/PermaLinkaspxguid=8dfbbe0c-7851-4cb8-8a49-150be21.aspx

Vale, hemos creado en cliente un validador llamado "numeropar" y hemos modificado nuestro atributo
para indicar que debe usarse la regla de validación en cliente llamada "numeropar". Parece que todo
debería funcionar​
pero todavía nos queda un último detalle.

Código javascript no obtrusivo


Por defecto ASP.NET MVC3 no solo usa jQuery Validate para las validaciones sino que
además usa la versión unobtrusive. No sé si conoces el significado de código javascript no
obtrusivo (unobtrusive javascript) pero resumiéndolo te puedo decir que se trata de que el
obtrusivo (unobtrusive javascript) pero resumiéndolo te puedo decir que se trata de que el
código javascript esté totalmente separado de las etiquetas HTML. Eso significa no ver más
los famosos onclick="​
" y similares. Las etiquetas HTML se mantienen totalmente limpias de
código javascript y contienen tan solo atributos HTML estándar. El uso de javasctipt no
obtrusivo se basa en una característica nueva de HTML5 (aunque es posible usar javascript
no obtrusivo en versiones anteriores, aunque no de forma tan elegante). Para más
información os remito a un post en mi blog donde comento más en detalle que es y cómo
funciona el javascript no obtrusivo:
http://geeks.ms/blogs/etomas/archive/2010/11/12/saca-tus-scripts-de-tu-c-243-digo-
html.aspx
Si miras el código fuente HTML que genera la llamada a Html.EditorFor(x=>ValorPar) verás lo siguiente:

<div class="editor-field">
<input class="text-box single-line" data-val="true" data-val-number="The field
ValorPar must be a number." data-val-numeropar="El número debe ser par." data-val-
range="Positivo menor que 100" data-val-range-max="100" data-val-range-min="1"
data-val-required="The ValorPar field is required." id="ValorPar" name="ValorPar"
type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="ValorPar" data-valmsg-
replace="true"></span>
</div>

Todos los atributos data-val que contiene el <input> son para las validaciones usando javascript no
obtrusivo. De hecho puedes observar que existe un atributo llamado data-val-numeropar. Ese atributo
se ha generado porque precisamente hemos implementado IClientValidatable en nuestro atributo de
servidor. Bien, por un lado tenemos un validador llamado "numeropar" que hemos dado de alta en
jQuery Validate. Por otro tenemos el atributo data-val-numeropar que se ha generado al implementar
IClientValidatable en nuestro atributo. Tan solo nos falta indicar a jQuery Validate que debe usar el
validador llamado "numeropar" en todos aquellos campos que tengan el atributo "data-val-numeropar".
Para ello debemos usar el siguiente código javascript:

$.validator.unobtrusive.adapters.addBool("numeropar");

Con este código se enlaza el validador numeropar de jQuery Validate, con el atributo data-val-
numeropar.

De hecho en el ejemplo el mismo nombre (​


numeropar​
) para todo, cosa que yo os recomiendo, pero
realmente tenemos dos conceptos:

1. El nombre del validador que damos de alta en jQuery Validate


2. El nombre de la regla de validación, es decir el nombre del atributo data-val-xx (donde xx se
sustituye por el nombre de la regla de validación).
No es obligatorio usar el mismo nombre. Con el siguiente código, dais de alta un validador
llamado "numeropar" y lo vinculáis a la regla de validación "np":
$.validator.addMethod("numeropar", function (value, element, param) {
return value % 2 == 0;
});
$.validator.unobtrusive.adapters.addBool("np", "numeropar");

Fijaos en el segundo parámetro del método addBool: indica que la regla "np" debe validarse usando el
validador "numeropar" (si no se pone el parámetro se asume que el nombre es el mismo).

Por supuesto ahora la regla se llama "np", y no "numeropar", por lo que cuando se implemente
IClientValidatable debe usarse "np":

public IEnumerable<ModelClientValidationRule>
GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
{
yield return new ModelClientValidationRule
{
ErrorMessage = this.ErrorMessage,
ValidationType = "np"
};

Bueno, el código completo de la vista quedaría:

@model MvcApplication2.Models.DemoModel
<h2>
ViewPage1</h2>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")"
type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"
type="text/javascript"></script>
<script type="text/javascript">
$.validator.addMethod("numeropar", function (value, element, param) {
return value % 2 == 0;
});
$.validator.unobtrusive.adapters.addBool("np", "numeropar");
</script>
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset>
<legend>DemoModel</legend>
<div class="editor-label">
@Html.LabelFor(model => model.ValorPar)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.ValorPar)
@Html.ValidationMessageFor(model => model.ValorPar)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}

¡Ahora sí! Hemos creado una validación propia y que se valida no solo en servidor sino también en
cliente!

En resumen
Hemos visto cómo funciona el sistema de validaciones basadas en atributos en ASP.NET
MVC3. También hemos visto lo sencillo que es crear nuestras propias validaciones usando
atributos propios y como añadir validación en cliente en javascript. Por supuesto os animo a
que entendáis como funciona jQuery Validate (hemos visto el tipo de validadores más
sencillos que existen, los que sólo validan un valor, pero los hay que pueden recibir
parámetros para validar rangos, o hacer comparaciones). No entraremos más en detalle en
jQuery Validate porque cae fuera del ámbito de este manual.
¿Y sobre las validaciones? Pues no hemos terminado todavía​
¡hay un par de cosillas más que creo
interesantes y que veremos en el siguiente artículo!

AqpHost
aqphost.com
hosting de calidad para tus clientes y tus proyectos web

Autor
Eduard Tomàs
Seguir a @eixim enis

Apasionado de la informática, los videojuegos, rol y... la cerveza. Key Consultant en


Pasiona y MVP en #aspnet 

Subir 
Subir 

Manual
Manual del framework ASP.NET MVC

 Validaciones en ASP.NET MVC Validaciones cruzadas 

Compartir

4 17

Com partir Tw eet

Recom endar

Comentarios
 Enviar un comentario al artículo

Eduardo
Mas articulos 07/3/2012
Hasta ahora el maual genial pero sería aún mejor si los artículos se publicaran con
mayor frecuencia, y ojala se tocaran mas temas para las vistas (ajax, jquery dropdowns
dependientes de otros dropdown, etc.

Pero me encanta este tema, gracias por su esfuerzo

Marcar como spam

 Enviar un comentario al artículo

Principales Monotemáticos Blogging


Manuales Desde cero Actualidad

FAQs HTML, CSS De interés

En directo Javascript, Ajax Agenda

Vídeos Diseño, ASP


Powered by:



Desarrolloweb.com Copyright Publicidad Acerca de Datos legales P. de cookies Contacta

S-ar putea să vă placă și