Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
Mostrando entradas con la etiqueta validadores. Mostrar todas las entradas
Mostrando entradas con la etiqueta validadores. Mostrar todas las entradas
martes, 9 de febrero de 2021
ASP.NET Core

Hoy voy a hablar de un cambio introducido en el framework hace ya algunos años, que, al menos en mi caso, pasó totalmente desapercibido en su momento y durante bastante tiempo después. Y he pensado que sería buena idea publicar sobre ello porque, como este mundo es así de grande, seguro que hay todavía algún despistado al que podría estar afectando a día de hoy y ni siquiera se ha dado cuenta :)

Como recordaréis, los atributos de validación [EmailAddress] y [Url], presentes en el espacio de nombres System.ComponentModel.DataAnnotations, los hemos utilizado durante años para asegurar que determinados valores de entrada eran direcciones de correo electrónico y URLs válidas, respectivamente:

public class Blog
{
    [Required, EmailAddress]
    public string ContactEmail { get; set; }
    [Required, Url]
    public string Url { get; set; }
}

Desde el principio de los tiempos, aún en ASP.NET "clásico", ambos atributos de validación utilizaban internamente complejas expresiones regulares para comprobar los valores, y la verdad es que funcionaban relativamente bien. Nuestras aplicaciones podían confiar en que valores que hubieran superado dichas validaciones serían, como mínimo, sintácticamente correctos y buenos candidatos a ser direcciones de correo o URLs válidas.

Pues bien, desde la llegada de NET 4.7.2, y luego en .NET Core, [EmailAddress] y [Url] ya no funcionan así. En palabras casi textuales del equipo de desarrollo, el objeto de estos dos atributos es simplemente prevenir algunos errores básicos al teclear, y no contemplar todas las posibilidades definidas en las respectivas RFC que describen la sintaxis de dichos valores.

martes, 20 de noviembre de 2012
ASP.NET MVCEn formularios ASP.NET MVC, por defecto los campos ocultos no son validados en cliente. Es decir, aunque estos campos hayan sido generados usando los helpers e incluyan atributos con las restricciones, no serán tenidos en cuenta por jQuery validate a la hora de validar los datos del formulario antes de enviarlos al servidor.
martes, 19 de junio de 2012
ASP.NET MVCUn post rapidito. Según puede consultarse en MSDN, ya tenemos confirmado que la versión 4.5 de .NET framework vendrá acompañada de un nuevo conjunto de atributos de validación para aplicar a las propiedades del Modelo en el espacio de nombres System.ComponentModel.DataAnnotations:
  • CreditCardAttribute, que puede ser utilizado para validar números de tarjeta de crédito.
  • EmailAddressAttribute, que validará direcciones de correo electrónico.
  • FileExtensionsAttribute, para validar extensiones en nombres de archivo.
  • PhoneAttribute, que indica cuándo una propiedad debe contener un número de teléfono válido.
  • UrlAttribute, que comprobará si el contenido de una propiedad es una URL válida.
  • CompareAttribute, que antes estaba disponible en System.Web.Mvc y ha “ascendido” a anotación de datos general, permite validar la igualdad de dos propiedades.
Pues bien, según se observa en este changeset del código fuente del framework, ya podemos asegurar que la versión final de MVC 4 incorporará adaptadores de cliente y servidor para que podamos utilizarlos de forma directa en nuestros desarrollos :-)

También se ha incluido soporte para el atributo MembershipPasswordAttribute, recientemente incluido en System.Web.Security, que comprueba si una contraseña cumple los requisitos establecidos para las mismas en el membership provider.

Publicado en Variable not found.
miércoles, 1 de febrero de 2012
Microsoft .NET Habitualmente asociamos la validación de entidades basadas en anotaciones de datos, o data annotations, a tecnologías como dynamic data o ASP.NET MVC, y estamos acostumbrados a que la validación se realice de forma automática, pero nada más lejos de la realidad. Podemos utilizar data annotations desde cualquier tipo de aplicación .NET (Webforms, Winforms, WPF, Consola, o cualquier otra en la que tengamos disponible System.ComponentModel.DataAnnotations), puesto que existe la posibilidad de invocar manualmente los procedimientos de validación.

En este post vamos a ver cómo realizar validaciones basadas en anotaciones de forma manual, lo cual puede tener su utilidad en gran número de escenarios.
martes, 22 de noviembre de 2011
ASP.NET MVCEl sistema de validación en cliente de ASP.NET MVC, como sabemos basado en jQuery validate, es el encargado de mostrar u ocultar los mensajes de error asociados a cada campo conforme va comprobando su validez.

Los mensajes de error asociados a cada validador son almacenados inicialmente en atributos data-val-* sobre el control a comprobar, y cuando se detecta un problema de validación, son mostrados copiando su contenido al interior de la etiqueta <span> que el helper Html.ValidationMessage() habrá generado sobre la página.

Sin embargo, al hilo de una consulta reciente en los foros de ASP.NET MVC en MSDN, perfectamente contestada por el amigo Eduard Tomás, pensé que realmente tenemos poco control sobre cómo se muestran estos errores, así que me he puesto un rato a ver cómo podíamos conseguir introducir lógica personalizada en este punto aprovechando la flexibilidad que ofrece jQuery validate 1.9.

Salvo por la escasez de documentación de este componente, tomar el control en el momento de mostrar los mensajes de error es bastante sencillo. Basta con establecer una función en la propiedad showErrors de los settings del plugin, cosa que podemos hacer con el siguiente script de inicialización:
<script type="text/javascript">
    $(function () {
        var settings = $.data($('form')[0], 'validator').settings;
        settings.showErrors = function (errorMap, errorList) {
            // Aquí el código personalizado:
            [...]

            // Y si nos interesa, finalmente podemos
            // ejecutar el comportamiento por defecto

            this.defaultShowErrors();
        };
    });
</script>
(Por simplificar, estamos asumiendo que en el formulario hay un único tag <form>, que es el que capturamos con el selector).

La función showErrors() recibe dos parámetros. El primero es un “mapa” donde asociamos a cada clave (nombre del campo) el mensaje de error que tenga asociado. Así, por ejemplo, el valor de errorMap.Nombre será nulo si el campo “Nombre” del formulario no tiene ningún error (ha validado correctamente), o el texto del error en caso contrario.

En el segundo parámetro de la función encontraremos un array con los errores a mostrar. En cada elemento tendremos disponible la propiedad element, desde la que podemos acceder al control que ha generado el error, y message, donde podemos consultar o establecer la descripción del mismo.

Es importante tener en cuenta que la función showErrors() es invocada con mucha frecuencia durante el proceso de edición (pérdida de foco, obtención de foco, pulsación de teclas…), por lo que desde el punto de vista de la usabilidad no tiene demasiado sentido introducir en ella procesos bloqueantes (como puede ser un alert()) o demasiado largos en el tiempo, para evitar que se solapen.

Por ejemplo, en el siguiente código utilizamos el efecto “highlight” de jQuery UI para resaltar con un rápido destello el elemento en el que se ha detectado un error:
    settings.showErrors = function (errorMap, errorList) {
        for (var i = 0; i < errorList.length; i++) {
            var error = errorList[i];
            // error.element es el elemento que ha provocado el error
            $(error.element).effect("highlight", { times: 1 }, 100);
        }
        this.defaultShowErrors();
    };
En fin, algo no demasiado útil ;-P, pero interesante en cualquier caso para profundizar un poco en los misterios e interioridades de jQuery validate.

Publicado en Variable not found.
jueves, 22 de septiembre de 2011
ASP.NET MVCComo ya sabréis (o no, pero yo os lo cuento ;-)), el próximo martes día 27 de septiembre, a las 19:00 (hora peninsular española, GMT+1) daré una charla con AUGES en la que trataremos los mecanismos de validación que encontramos en ASP.NET MVC 3.

El tema, que ha sido propuesto por algunos de vosotros, es sin duda muy interesante. Sea cual sea el tipo de aplicación que desarrollemos, nos vemos obligados a validar los datos de entrada y, afortunadamente, MVC 3 viene acompañado de un sistema realmente potente para ayudarnos con esta crítica tarea. De hecho, es tan amplio que no es fácil conocerlo en toda su extensión.

Y lo que voy a intentar en esta charla es dar un repaso al sistema de validación de MVC 3 completo. De esta forma podréis conocer qué es lo que hay, lo que se puede hacer, y tener una idea de cómo hacerlo. Trataremos desde aspectos muy simples como las anotaciones incluidas en el framework, su personalización y extensión, hasta temas algo más avanzadillos como la creación de validadores en cliente o los proveedores de validación. Espero que me dé tiempo a todo, uuf!

Para poder seguirla creo que es conveniente (por no decir necesario) conocer ASP.NET MVC 3 (o 2) al menos a un nivel básico; no voy a tener tiempo para detenerme en ver qué es un controlador, cómo le llegan los parámetros a la acciones, o cómo se construye un formulario. Pero tampoco es que sean unos requisitos muy exigentes: cualquiera que haya jugado mínimamente con el framework creo que podrá entenderlo todo… o al menos ese es el objetivo.

Os recuerdo que se trata de un Webcast, o sea, que podéis asistir a este evento desde vuestro sillón favorito y con un saco de palomitas a la vera, y por supuesto es totalmente gratuito. Eso sí, debéis registraros previamente para poder asistir:
En fin, os dejo, que tengo que preparar una charla… ;-)
martes, 26 de abril de 2011
ASP.NET MVCSi a día de hoy hay algo fatalmente poco resuelto en ASP.NET MVC, es sin duda la localización. Aunque con un poco de paciencia se pueden poner en marcha sistemas completamente adaptados a distintos idiomas y culturas, la verdad es que se echa en falta una mayor consideración, entre otros, con los que osamos utilizar la coma para separar la parte entera de la decimal en un número.

Hace tiempo traté el tema por aquí, y aporté una solución para la versión 2 de ASP.NET MVC, que aún utilizaba las bibliotecas de scripting de Microsoft Ajax. Sin embargo, la versión 3 ha sustituido “de serie” esos componentes por jQuery Validate y el magnífico sistema de validaciones no intrusivas, por lo que todo lo dicho en aquella ocasión no vale ya para nada :-(

Validación decimal incorrectaEl problema radica en que el plugin jQuery Validate utiliza únicamente el punto como separador de decimales, por lo que la validación en cliente de valores de tipo decimal, float o double que utilicen la coma finalizará siempre en un error e impedirá el envío del formulario, como puede observarse en la captura de pantalla de la derecha.

Por cierto, antes de que se me olvide, hace unos meses reportaron este asunto como bug en Microsoft Connect. Si el tema os preocupa, podéis ir y votarlo a ver si conseguimos que este asunto se tenga en cuenta en próximas revisiones.

Sin embargo, estrictamente hablando, no se trata de un bug de ASP.NET MVC, puesto que la validación en cliente ha sido delegada por completo al plugin de jQuery, y éste es el que no tiene en cuenta los aspectos de internacionalización. Desde este punto de vista, quizás tendría más sentido, por tanto, esta issue reportada en Github sobre jQuery Validate, que propone su integración de forma nativa con jQuery Global.

Por tanto, me temo que se trata de un asunto de responsabilidad compartida (y dispersa, por tanto) entre los equipos de MVC, de jQuery Validate, y no sé si de alguno más. Esperemos que entre todos puedan solucionar de forma razonable el problema.

En cualquier caso, los que ya estamos creando aplicaciones con MVC 3 no podemos esperar las soluciones oficiales, que seguro llegarán más tarde o más temprano, y nos vemos obligados a buscar alternativas que nos permitan convivir con este problema de la forma más cómoda posible.

Y esto es lo que veremos en este post: varias posibilidades que tenemos para que la validación en cliente de valores decimales no nos compliquen demasiado la vida. Seguro que hay más, seguro que las hay mejores, pero ahí van unas cuantas opciones que nos pueden ayudar en escenarios como el descrito anteriormente.

1. Desactivar la validación en cliente

Está claro que el problema es en cliente, por lo que si desactivamos estas validaciones y dejamos que sea el servidor el que se encargue de comprobar que los valores de los distintos campos cumplen las restricciones impuestas por su tipo y las anotaciones de datos, ya no nos afectará más la absoluta indiferencia de jQuery Validate hacia las particularidades culturales.

Esto podemos conseguirlo de varias formas:
  • desactivar la validación en cliente de forma global, estableciendo a false la propiedad clientValidationEnabled en el web.config, lo cual dejará a toda la aplicación sin validaciones en cliente. Como solución es algo drástica, pero poderse se puede.
  • desactivar la validación en cliente de forma local, sólo en aquellos formularios en los que existan propiedades de tipo decimal, introduciendo el siguiente código Razor (o su correspondiente en ASPX) antes de la llamada a BeginForm():
    @{    
       Html.EnableClientValidation(false);
    }
    
  • desactivar la validación en cliente sólo en el campo que nos interese, que podemos conseguir introduciendo el siguiente script, imaginando que el campo decimal en el que queremos anular la validación en cliente tiene como identificador “Altura”:
    <script type="text/javascript">
       $("#Altura").removeAttr("data-val");
    </script>
Aunque podemos utilizar cualquiera de estas tres opciones,sin duda la menos violenta es la última, pues permite disfrutar de las validaciones en cliente y que sólo sean ignorados los campos conflictivos.

2. Modificar jQuery Validate

Esta es una solución algo bestia que he encontrado por ahí, pero soluciona el problema de un plumazo: modificar el código de jQuery Validate para que acepte comas en lugar de puntos para separar los dígitos decimales de los enteros tanto en la validación numérica como en los rangos.

En el blog de Lenard Gunda podéis encontrar de forma muy detallada los cambios a realizar al archivo jquery.validate.js (o a su versión minimizada). Hay, sin embargo, un par de detalles que debemos tener en cuenta si optamos por esta solución:
  • primero, que nos estamos separando de la distribución oficial del plugin. Si actualizamos la biblioteca jquery.validate, por ejemplo utilizando Nuget, volveremos a tenerlo todo como al principio, y tendremos que volver a introducir los cambios oportunos.
  • segundo, que esto no nos ayudará en aplicaciones adaptadas a varios idiomas; si modificamos el plugin para que acepte comas como separador, ya no volverá a aceptar el punto. Una solución rápida que se me ocurre para esto es tener dos versiones de la biblioteca (la original y la modificada), y referenciar desde la página la apropiada para la cultura actual.

3. Modificar la forma en que jQuery Validate parsea los decimales

Afortunadamente, el plugin de validación para jQuery es muy flexible, y permite introducir código personalizado para la validación de formato numérico y comprobación de rangos, lo que nos brinda la posibilidad de solucionar nuestro problema de forma muy limpia.

El siguiente código sería una primera aproximación a la solución del problema. Como podéis observar, simplemente introducimos en $.validator.methods.number y $.validator.methods.range las funciones que queremos utilizar para validar respectivamente los números y los rangos, reemplazando la coma por el punto antes de realizar la conversión con parseFloat():
<script type="text/javascript">
    $.validator.methods.number = function (value, element) {
        value = floatValue(value);
        return this.optional(element) || !isNaN(value);
    }
    $.validator.methods.range = function (value, element, param) {
        value = floatValue(value);
        return this.optional(element) || (value >= param[0] && value <= param[1]);
    }
 
    function floatValue(value) {
        return parseFloat(value.replace(",", "."));
    }  
</script>

Si incluimos este script en la página cuando la cultura activa sea la nuestra (o cualquier otra que también utilice la coma para separar decimales), tendremos el problema solucionado.

Una fórmula más elegante y universal sería modificar la función floatValue(), y en lugar de reemplazar de forma manual los caracteres, utilizar el plugin Global para realizar la conversión a flotante según la cultura actual. Los detalles de esto, sin embargo, los dejo para otro post.

En fin, que como habréis comprobado existen mil y un enfoques posibles para enfrentarnos al problema. Espero que las ideas que hemos ido comentando os sean de utilidad para implementar vuestras propias soluciones hasta que tengamos una vía “oficial” para conseguirlo.

Publicado en: Variable not found.
miércoles, 16 de diciembre de 2009

Validación de formularios ASP.NET desde javascript Cada vez que tengo que forzar la validación de los datos de un formulario Webforms mediante javascript me veo obligado a preguntarle a Google, ese que todo lo sabe, cómo era el nombre de la función. Cosas de la edad, supongo ;-)

Así que, a modo de auto-recordatorio y con la intención de que pueda ser útil a alguien más, ahí va: la función se llama Page_ClientValidate(). Retorna “true” si, una vez evaluados todos los validadores de la página, el valor de los campos es correcto (al menos en cliente; otra cosa son las comprobaciones en servidor, p.e., las definidas en un CustomValidator).

Y como ejemplo de uso, puede valer el siguiente. Se trata de un botón de envío en un formulario donde se compone un correo electrónico:

   1: ...
   2: <asp:Button ID="btnEnviar" runat="server" Text="Enviar mail" 
   3:      OnClick="btnEnviar_Click"
   4:      OnClientClick="return confirmar();"
   5: />
   6: ...
   7:  
   8: <script type="text/javascript">
   9:     function confirmar() {
  10:         if (!Page_ClientValidate())   // Fuerza la validación en cliente
  11:             return false;             
  12:             
  13:         return confirm('¿Seguro que desea realizar el envío?');
  14:     }
  15: </script>

Como se puede observar, en el atributo OnClientClick del botón incluye un script en el que se retorna el valor devuelto por la función confirmar. Si el retorno es false, se cancela el Postback, evitando así que se invoque al evento btnEnviar_Click que es el que realiza el envío del mail propiamente dicho.

En el cuerpo de la función confirmar(), en primer lugar, validamos la página; si ésta no supera el proceso, los validadores habrán mostrado sus mensajes de error y retornamos falso, haciendo que se anule el postback. Si la validación es correcta, solicitamos al usuario que confirme la acción y retornamos su decisión.

Publicado en: Variable not found.

jueves, 10 de abril de 2008
Pablo ha lanzado una pregunta en el post Deshabilitar y habilitar un validador ASP.Net desde Javascript publicado hace unos meses, que creo interesante responder en una entrada en exclusiva, por si puede ayudar a alguien más.
"Al utilizar la funcion ValidatorEnable para habilitar un validador, me activa automaticamente la validacion, y me muestra el texto que pongo para cuando la validacion no se cumpla, como puedo evitar esto"

Recordemos que el post trataba sobre cómo conseguir, desde Javascript, habilitar o deshabilitar validadores de controles incluidos en un webform utilizando la función ValidatorEnable(), que pone a nuestra disposición ASP.Net.

El problema, como comenta Pablo, es que al habilitar la validación desde script se muestran de forma automática los mensajes de error en todos aquellos controles que no sean válidos, provocando un efecto que puede resultar desconcertante para el usuario.

Indagando un poco, he comprobado que el problema se debe a que ValidatorEnable(), después de habilitar el validator, comprueba si los valores del control son correctos, mostrando el error en caso contrario.

Existen al menos dos formas de solucionar este problema.

La primera consiste en jugar con la visibilidad del mensaje de error. Como se observa en el siguiente código, al llamar a la función HabilitaValidador(), ésta llamará a ValidatorEnable y acto seguido, si el control no es válido, oculta el mensaje de error:

function HabilitaValidador(validator, habilitar)
{
ValidatorEnable(validator, habilitar);
if (habilitar && !validator.isvalid)
validator.style.visibility = "hidden";
}
 
La segunda forma consiste en simular el comportamiento interno de ValidatorEnable, pero eliminando la llamada a la comprobación de la validez del control.

function HabilitaValidador(validator, habilitar)
{
validator.enabled = habilitar;
}
 
Como se puede ver, simplemente se está estableciendo la propiedad enabled del validador, sin realizar ninguna comprobación posterior.

En ambos casos, la forma de utilizar esta función desde script sería la misma:

function activar()
{
HabilitaValidador("<%= RequiredFieldValidator1.ClientID %>", true);
}
 
Para mi gusto la opción más limpia, aunque sea jugando con la visibilidad de los elementos, es la primera de las mostradas, pues se respeta el ciclo completo de validación. En el segundo método nos estamos saltando las validaciones y el seguimiento de la validez global de la página, que la función original ValidatorEnable sí contempla.

Espero que esto resuelva la duda.

Publicado en: www.variablenotfound.com.