Modelo
public class IndexModel { public bool AceptoCondiciones { get; set; } }Vista
@using (Html.BeginForm()) { <div>@Html.CheckBoxFor(m => m.AceptoCondiciones) Acepto las condiciones de uso</div> <div>@Html.ValidationMessageFor(m => m.AceptoCondiciones)</div> <input type="submit" value="Enviar" /> }La idea es comprobar que el usuario acepta las condiciones de uso. Algo bastante típico en formularios de registro. La primera idea fue marcar la propiedad AceptoCondiciones con el DataAnnotation [Required], pero tras escribirlo (no hizo falta ni probarlo) me di cuenta que no iba a funcionar, ya que el checkbox siempre tiene un valor, o verdadero o falso (marcado o desmarcado) por lo que la regla Required no nos valdría.
Tras mirar y mirar por google y darme cuenta que ya llevaba bastante tiempo perdido no me quedo más remedio que lanzarme a hacer mi propio validador. Para hacer una validador propio tan solo debemos heredar de la clase ValidationAttribute y sobreescribir el método IsValid. Pensando en el futuro añadí una propiedad ValidValue que nos indica cual es el valor que damos por válido, no sea que alguna vez necesite tener desmarcado un check. Con esto el validador quedaría así
public class IsTrueOrFalseAttribute : ValidationAttribute { ///Y añadimos el atributo al modelo/// Valor permitido /// public bool ValidValue { get; set; } public override bool IsValid(object value) { if (value == null || value.GetType() != typeof(bool)) return false; return ((bool)value == ValidValue ? true : false); } }
public class IndexModel { [IsTrueOrFalse(ValidValue=true)] public bool AceptoCondiciones { get; set; } }Con esto esto ya podemos probar nuestro validador y ver que funciona de la manera esperada
Pero, siempre hay un pero, este validador presenta un problema y es que siempre irá al servidor para realizar la validación. En mi caso no hay problema porque en el formulario de registro siempre voy al servidor para comprobar algunas cosas, como el nombre de usuario, pero en otros escenarios puede ser que no tengamos que ir al servidor para nada, e ir para solo comprobar si un checkbox está marcado es innecesario.
Como me gusta investigar y aprender cosas nuevas, decidí hacer que mi validador también tuviera soporte para cliente. La verdad es que esta parte está bastante mal documentada pero básicamente lo primero que tenemos que hacer es que nuestro validador implemente la interfaz IClientValidatable. En nuestro caso el validador quedaría de la siguiente manera
public class IsTrueOrFalseAttribute : ValidationAttribute, IClientValidatable { ///Y luego en un fichero .js debemos añadir el siguiente código/// Valor permitido /// public bool ValidValue { get; set; } public override bool IsValid(object value) { if (value == null || value.GetType() != typeof(bool)) return false; return ((bool)value == ValidValue ? true : false); } IEnumerable<modelclientvalidationrule> IClientValidatable.GetClientValidationRules(ModelMetadata metadata, ControllerContext context) { var rule = new ModelClientValidationRule { ErrorMessage = String.IsNullOrEmpty(ErrorMessage) ? FormatErrorMessage(metadata.PropertyName) : ErrorMessage, ValidationType = "istrueorfalse" }; // Transformamos el valor boolean a un string en minúsculas para que no falle la transformación en cliente de string a boolean. rule.ValidationParameters["validvalue"] = (this.ValidValue ? "true" : "false"); yield return rule; } }
$.validator.addMethod("istrueorfalse", function (value, element, param) { // Comparamos el valor checked del elemento con el valor permitido pasado por parámetro return element.checked == Boolean(param.validvalue); }); $.validator.unobtrusive.adapters.add('istrueorfalse', ['validvalue'], function (options) { options.rules['istrueorfalse'] = options.params; options.messages['istrueorfalse'] = options.message; });Si ejecutamos nuestro código veremos que realiza la validación sin la necesidad de ir a cliente.
Nota: Para activar las validaciones en cliente (pese a que en ASP.NET MVC4 ya viene por defecto) debemos asegurarnos que tenemos estas lineas en el web.config
<appSettings> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> </appSettings>También hay que comprobar que tenemos añadidas las referencias a los scripts jquery-1.6.2.js, jquery.validate.js, jquery.validate.unobtrusive.js y al fichero que creemos para añadir las lineas donde añadimos el validador y el adaptador.
Como vemos tampoco es extraordinariamente complicado validar nuestros datos en cliente así que, lo mejor que podemos hacer es hacerlo...
Happy coding!
No hay comentarios:
Publicar un comentario