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 .net. Mostrar todas las entradas
Mostrando entradas con la etiqueta .net. Mostrar todas las entradas
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, 27 de diciembre de 2011
Enlaces interesantes: .NET, ASP.NET, Azure, HTML, CSS, javascript, Visual StudioEstos son los enlaces publicados en Variable not found en Facebook y Twitter del 18 al 23 de diciembre de 2011. Espero que os resulten interesantes. :-)

.Net

Asp.net

Azure / Cloud

Data access

Html/Css/Javascript

Visual Studio/Complementos

Y no olvidéis que podéis seguir esta información en vivo y en directo desde Variable not found en Facebook, o a través de Twitter.

Publicado en Variable not found
lunes, 19 de diciembre de 2011
Enlaces interesantes: .NET, ASP.NET, Azure, HTML, CSS, Visual StudioEstos son los enlaces publicados en Variable not found en Facebook y Twitter del 12 al 17 de diciembre de 2011. Espero que os resulten interesantes. :-)

Aprovecho además para pediros opinión sobre un nuevo formato de presentación de los enlaces, usando categorizaciones. De esta forma podréis acceder directamente a aquellos cuya temática os interese, en lugar de tener que leerlos todos para ver si hay alguno que al que valga la pena echar el vistazo. ¿Qué os parece? ¿Mejor así?

.Net

Asp.net

Azure / Cloud

Conceptos

Data access

Html/Css/Javascript

Visual Studio/Complementos

Otros

Y no olvidéis que podéis seguir esta información en vivo y en directo desde Variable not found en Facebook, o a través de Twitter.

Publicado en Variable not found
lunes, 31 de mayo de 2010
.NET Los parámetros opcionales son una interesante ayuda que hace tiempo que está presente en otros lenguajes como Visual Basic .NET, y ha sido introducida en la versión 4.0 de C#, para alegría de muchos.

A grandes rasgos, esta característica nos permite especificar valores por defecto para los parámetros de nuestros métodos, ahorrándonos tiempo de codificación:

class Program
{
    public static void Main(string[] args)
    {
        Muestra();            // Imprime 1,1
        Muestra(8);           // Imprime 8,1
        Muestra(3,4);         // Imprime 3,4
        Console.ReadKey();
    }
 
    static void Muestra(int a=1, int b=1)
    {
        Console.WriteLine(a + "," + b);
    }
}

Desde siempre, ignorante de mí, había pensado que esto no era más que una triquiñuela del compilador, un azucarillo sintáctico destinado a facilitarnos la creación de sobrecargas de forma rápida, pero, ahora que lo he estudiado algo más a fondo, resulta que no es así. De hecho, los parámetros opcionales están soportados a nivel de plataforma, y funcionan de forma algo extraña (o al menos diferente a lo que podía esperarse), por lo que es conveniente conocerlos bien para no cometer determinados errores.

En primer lugar, me ha llamado la atención que la detección de la ausencia de parámetros en la llamada y la asignación de los valores por defecto no la realiza el método en el que se han definido. Es decir, sobre el ejemplo anterior, no es el método Muestra() el que comprueba si se han suministrado valores para los parámetros a y b, ni el que le asigna los valores por defecto en caso contrario. Esta "comprobación" se realiza en tiempo de compilación (!).

Esto lo demostramos muy fácilmente si descompilamos esta misma aplicación con ayuda del imprescindible Reflector, que nos mostrará el siguiente código:

class Program
{
    public static void Main(string[] args)
    {
        Muestra(1, 1);
        Muestra(8, 1);
        Muestra(3, 4);
        Console.ReadKey();
    }
 
    public static void Muestra([Optional, DefaultParameterValue(1)] int a, 
     [Optional, DefaultParameterValue(1)] int b)
    {
        Console.WriteLine(a + ", " + b);
    }
}

Como se puede observar, se ha generado un método Muestra() cuyos parámetros incluyen atributos que indican su opcionalidad y el valor por defecto en cada caso.

Pero lo curioso está en el método Main(), desde donde se hacen las llamadas, el que podemos observar que las invocaciones a Muestra() incluyen valores para todos los parámetros, como si se tratara de constantes especificadas directamente por el desarrollador.

Por tanto, no hay nada mágico en los métodos con parámetros opcionales, ni sobrecargas, ni código de comprobación o asignación insertado de forma automática. Es el propio compilador el que, en el momento de generar el código IL, extrae los valores por defecto de los parámetros no especificados en la llamada examinando los atributos presentes en la signatura y los introduce en la invocación.

Y es aquí justo donde hay que tener cuidado al utilizar los parámetros opcionales. Dado que el valor de los parámetros se determina en tiempo de compilación y se incluyen como constantes en el código IL generado, pueden producirse efectos no deseados si trabajamos con distintos ensamblados.

Veámoslo con un ejemplo, que, aunque poco real, creo que ilustrará un escenario donde los parámetros opcionales podrían jugarnos una mala pasada.

En el siguiente código, perteneciente al ensamblado LogicaNegocio.dll, vemos un método CalculaImporteconIva(), que retorna un importe aplicándole el impuesto (IVA) correspondiente:

public class LogicaNegocio
{
    public double CalculaImporteConIva(double importe, double iva = 0.16)
    {
        return importe + importe*iva;
    }
}

Así, podemos tener un ensamblado externo, pongamos ERP.exe, que haga uso de este método de la siguiente forma:

public void muestraDesglose(double importe)
{
    double importeTotal = logica.CalculaImporteConIVA(importe)
    // Mostrarlo...
}

En el momento de compilación de ERP.exe, la llamada anterior quedará en el ensamblado resultante igual que si hubiéramos hecho esta llamada:
 
    double importeTotal = logica.CalculaImporteConIVA(importe, 0.16)

Si ahora se produce una subida de IVA (como lamentablemente va a ocurrir en breve), acudiríamos a modificar el valor por defecto del parámetro iva en el método CalculaImporteConIva() y recompilaríamos LogicaNegocio.dll:

public class LogicaNegocio
{
    public double CalculaImporteConIva(double importe, double iva = 0.18)
    {
        return importe + importe*iva;
    }
}

Sin embargo, si no recompilamos ERP.EXE desde éste seguiríamos enviándole el valor anterior (0.16, recordad que este valor aparece como constante en el ensamblado), lo que podía provocar algún problema. Es decir, si queremos mantener la coherencia del sistema, nos veríamos obligados a recompilar todos los ensamblados que referencien LogicaNegocio.dll.

Conclusión: en métodos públicos, y especialmente en aquellos que serán consumidos desde ensamblados externos, es conveniente utilizar parámetros opcionales sólo cuando los valores constantes sean “verdades universales”, como las constantes matemáticas o datos que con toda seguridad no van a cambiar.  No es buena idea utilizarlos para reflejar valores variables o constantes de lógica de negocio, con posibilidades de cambio aunque sean remotas.

Por último, comentar que aunque este post está centrado en C#, todas estas precauciones son igualmente válidas para Visual Basic .NET.

Publicado en: Variable not found
miércoles, 21 de abril de 2010
¿Sómos los primeros en llegar al estadio? Casualmente encuentro en el post de Chris Eargle “Any() versus Count()” un tema del que pensaba escribir hace tiempo y al final dejé en el tintero: ¿cómo podemos determinar si una enumeración está vacía? Vale, es bien fácil, una enumeración está vacía si tiene cero elementos.

Si trabajamos con un array, podemos consultar la propiedad Length; si se trata de una colección, podemos utilizar la propiedad Count, que también nos devolverá el mismo dato de forma directa.

Sin embargo, cuando procesamos información es frecuente tratar con tipos de datos enumerables cuya implementación exacta desconocemos, y en los que no tenemos acceso a ninguna propiedad que nos permita conocer el número de elementos exactos que tiene almacenados. Por ejemplo, esto ocurre cuando obtenemos un conjunto de datos en forma de IEnumerable o trabajamos con LINQ sobre alguna fuente de información.

Pues bien, en estos casos hay que ser algo prudentes con la forma de consultar el número de elementos. Me he topado con código propio en el que, simplemente por despiste, utilizaba el método Count(), facilitado por LINQ para las enumeraciones y otras colecciones de datos, con objeto de saber si una lista estaba vacía:

var prods = services.GetProductsByCategory(category);
if (prods.Count() > 0)
{
   // Hacer algo con los elementos de la lista
}
else
{
   // No hay elementos
}

Seguro que ya os habréis percatado de que eso está mal, muy mal. El método Count() recorrerá uno por uno los elementos para contarlos, retornando el número exacto de ellos. En escenarios de un gran número de elementos, o cuando es costoso obtener cada elemento (como al traerlos de una base de datos) puede suponer un consumo de recursos enorme.

Y justo por esto existe el método Any(), que comprueba únicamente si existe al menos un elemento en la colección. Internamente este método itera sobre la colección retornando true cuando encuentra el primer elemento, por lo que es mucho más eficiente que el anterior:

var prods = services.GetProductsByCategory(category);
if (prods.Any()) // Mucho mejor :-)
{
  // Hacer algo con los elementos de la lista
}
else
{
  // No hay elementos
}

La utilización de Any() también es interesante para comprobar la existencia de elementos que cumplan una condición, expresada en forma de predicado; retornará true cuando encuentre el primer elemento que lo haga cierto:

if (pedidos.Any(p => p.Pendiente))
{
   // Mostrar alerta, hay al menos un pedido pendiente
}

Estamos en la puerta de un Estadio y queremos saber si vamos a ser los primeros en entrar al recinto… ¿le preguntaríamos al portero el número exacto de aficionados que ya están dentro para, si es cero, saber que somos los primeros? ¿O nos bastaría simplemente con preguntarle si hay alguien? ;-P

Publicado en: Variable not found
Hey: ¡estoy en Twitter!
domingo, 4 de abril de 2010
Hace casi un año hablaba de la segunda versión de NDepend, una herramienta capaz de ayudaros a mejorar nuestro código, analizando cientos de aspectos, métricas y reglas a nivel de fuentes y ensamblados.

Recientemente se ha publicado la tercera versión de NDepend, que ofrece interesantes novedades respecto a las anteriores, como la integración absoluta con Visual Studio, el soporte para soluciones multi-proyecto, potentes mecanismos de búsqueda, edición múltiple de CQL, o el seguimiento de cambios, además de las tradicionales características del producto.

Los 10 métodos más extensos de ASP.NET MVC 2
Pero sin duda, lo que me ha parecido más espectacular es su magnífica integración con Visual Studio (2005, 2008 y 2010), que permite disfrutar de toda la potencia de análisis de NDepend, y sus facilidades para la navegación desde el mismo entorno de desarrollo.

Para habilitar esta característica es necesario instalar el plugin en el IDE, que se realiza desde el propio entorno visual de NDepend:

Instalar plugin NDepend en Visual Studio
De esta forma, ya no es necesario acudir a la herramienta Visual NDepend para realizar búsquedas, comprobar reglas o navegar a través de la base de código: lo haremos directamente desde VS, utilizando los menús contextuales. Y gracias a ello, podemos disfrutar de las nuevas opciones de navegación, que nos permitirá surcar el código utilizando rutas distintas a las habituales:

Navegar por el código con NDepend
U obtener diagramas de dependencias de componentes, utilizando el botón derecho del ratón:

Dependencias con NDepend 3

Además, como comenta Patrick Smacchia, padre de la criatura, el rendimiento del entorno prácticamente no se resiente, dado que los análisis se ejecutan en segundo plano de forma incremental.

Recordar, por último, que NDepend es una aplicación comercial, pero dispone de una versión limitada gratuita utilizable por universidades, desarrolladores open source e incluso, durante un tiempo determinado, de prueba en proyectos comerciales.

Página del producto: http://www.ndepend.com/
Publicado en: Variable not found
Hey, ¡estoy en twitter!
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.

miércoles, 4 de noviembre de 2009

Cadenas Encuentro en el blog de Gunnar Peipman un post sobre el nuevo método string.IsNullOrWhiteSpace, aparecido en .NET Framework 4.0 Beta 2, cuya misión es retornar un booleano indicando si la cadena pasada como parámetro contiene un nulo, está vacío, o exclusivamente caracteres de espaciado (espacios, saltos de línea, tabulaciones, etc.), un escenario bastante frecuente cuando estamos, por ejemplo, validando formularios o cualquier tipo de datos de entrada.

Por si no podemos esperar hasta la llegada de la nueva versión del framework, Gunnar propone una solución temporal basada en crear un método de extensión sobre la clase string que realice la misma tarea:

 
public static class StringHelper
{
    public static bool IsNullOrWhiteSpace(this string s)
    {
        if (s == null)
            return true;
 
        return (s.Trim() == string.Empty);
    }
}
 
Como ya comenté por aquí hace tiempo, la ventaja que tiene utilizar esta técnica es que permite invocar el método sobre una instancia de cadena, aunque ésta sea nula, sin riesgo a errores:
 
string a = null;
string b = "    ";
string c = "\n";
string d = "Hey!";
Console.Write (a.IsNullOrWhiteSpace()); // True
Console.Write (b.IsNullOrWhiteSpace()); // True
Console.Write (c.IsNullOrWhiteSpace()); // True
Console.Write (d.IsNullOrWhiteSpace()); // False

Y para los fieles a Visual Basic .NET, ahí va el código equivalente:

Imports System.Runtime.CompilerServices
Public Module StringHelper
    <Extension()> _
    Public Function IsNullOrWhiteSpace(ByVal s As String) As Boolean
        If s Is Nothing Then
            Return True
        End If
        Return s.Trim() = String.Empty
    End Function
End Module

Publicado en: Variable not found.