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!
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.
domingo, 6 de abril de 2008
Semanas atrás publicaba el post "101 citas célebres del mundo de la informática", la traducción del post original de Timm Martin en Devtopics, "101 Great computer quotes". El tema me pareció tan divertivo e interesante que he realizado una nueva recopilación de otras tantas frases relacionadas con el mundo de la informática, y con especial énfasis en el desarrollo de software.

Este es el segundo post de la serie compuesta por:
miércoles, 2 de abril de 2008
Piezas de puzzleAunque las clases parciales aparecieron hace unos años, con la llegada de .Net 2.0 y Visual Studio 2005, vamos a hacer un breve repaso como preparación para un próximo post que trate los métodos parciales.

Las clases parciales (llamados también tipos parciales) son una característica presente en algunos lenguajes de programación, como C# y VB.Net, que permiten que la declaración de una clase se realice en varios archivos de código fuente, rompiendo así la tradicional regla "una clase, un archivo". Será tarea del compilador tomar las porciones de los distintos archivos y fundirlas en una única entidad.

En VB.Net y C#, a diferencia de otros lenguajes, es necesario indicar explícitamente que una clase es parcial, es decir, que es posible que haya otros archivos donde se continúe la declaración de la misma, usando en ambos con la palabra clave partial en la definición del tipo:
  ' VB.NET 
Public Partial Class Persona
...
End Class

// C#
public partial class Persona
{
...
}
 
En este código hemos visto cómo se declara una clase parcial en ambos lenguajes, que es prácticamente idéntica salvo por los detalles sintácticos obvios. Por ello, a partir de este momento continuaré introduciendo los ejemplos sólo en C#.

Pero antes un inciso: la única diferencia entre ambos, estrictamente hablando, es que C# obliga a que todas las apariciones de la clase estén marcadas como parciales, mientras que en VB.Net puede dejarse una de ellas (llamémosla "declaración principal") sin indicar que es parcial, y especificarlo en el resto de apariciones. En mi opinión, esta no es una práctica recomendable, por lo que aconsejaría utilizar el modificador partial siempre que la clase lo sea, e independientemente del lenguaje utilizado, pues contribuirá a la mantenibilidad del código.

El número de partes en las que se divide una clase es indiferente, el compilador tomará todas ellas y generará en el ensamblado como si fuera una clase normal.

Para comprobarlo he creado un pequeño código con dos clases exactamente iguales, salvo en su nombre. Una de ellas se denomina PersonaTotal, y está definida como siempre, en un único archivo; la otra, PersonaParcial, es parcial y la he troceado en tres archivos, como sigue:
  // *** Archivo PersonaParcial.Propiedades.cs ***
// Aquí definiremos todas las propiedades

partial class PersonaParcial
{
public string Nombre { get; set; }
public string Apellidos { get; set; }
}

// *** Archivo PersonaParcial.IEnumerable.cs ***
// Aquí implementaremos el interfaz IEnumerable

partial class PersonaParcial: IEnumerable
{
public IEnumerator GetEnumerator()
{
throw new NotImplementedException();
}
}

// *** Archivo PersonaParcial.Metodos.cs ***
// Aquí implementaremos los métodos que necesitemos

partial class PersonaParcial
{
public override string ToString()
{
return Nombre + " " + Apellidos;
}
}
 
Y efectivamente, el resultado de compilar ambas clases, según se puede observar con ILDASM es idéntico:

Clases generadas tras la compilación

A la hora de crear clases parciales es conveniente tener los siguientes aspectos en cuenta:
  • Los atributos de la clase resultante serán la combinación de los atributos definidos en cada una de las partes.
  • El tipo base de los distintos fragmentos debe ser el mismo, o aparecer sólo en una de las declaraciones parciales.
  • Si se trata de una clase genérica, los parámetros deben coincidir en todas las partes.
  • Los interfaces que implemente la clase resultante será la unión de todos los implementados por las distintas secciones.
  • De la misma forma, los miembros (métodos, propiedades, campos...) de la clase final será la unión de todos los definidos en las distintas partes.

Vale, ya hemos visto qué son y cómo se usan, pero, ¿para qué sirven? ¿cuándo es conveniente utilizarlas? Pues bien, son varios los motivos de su existencia, algunos discutibles y otros realmente interesantes.

En primer lugar, no era sencillo que varios desarrolladores trabajaran sobre una misma clase de forma concurrente. Incluso utilizando sistemas de control de versiones (como Sourcesafe o Subversion), la unidad mínima de trabajo es el archivo de código fuente, y la edición simultánea podía generar problemas a la hora de realizar fusiones de las porciones modificadas por cada usuario.

En segundo lugar, permite que clases realmente extensas puedan ser troceadas para facilitar su comprensión y mantenimiento. Igualmente, puede utilizarse para separar código en base a distintos criterios:
  • por ejemplo, separar la interfaz (los miembros visibles desde el exterior de la clase) y por otra los miembros privados a la misma
  • o bien separar las porciones que implementan interfaces, o sobreescriben miembros de clases antecesoras de los pertenecientes a la propia clase
  • o separar temas concernientes a distintos dominios o aspectos
En tercer lugar, aunque da la impresión que fue el motivo más importante para decidir su inclusión, las clases parciales permiten utilizar de forma efectiva herramientas automáticas de generación de código.

Así, es posible que un desarrollador y un generador estén introduciendo cambios sobre la misma clase sin molestarse, cada uno jugando con su propia porción de la clase; el primero puede introducir funcionalidades sin preocuparse de que una nueva generación automática de código pueda machacar su trabajo. Visual Studio y otros entornos de desarrollo hacen uso intensivo de esta capacidad, por ejemplo, en los diseñadores visuales de Windows Forms, WPF, ASP.Net e incluso el generador de modelos de LinqToSql.

Publicado en: http://www.variablenotfound.com/.
domingo, 30 de marzo de 2008
MundoVía Dirson me entero de que Google ha publicado recientemente el API que permite, a base de Ajax, realizar traducciones de textos entre los idiomas contemplados por la herramienta, más de una decena.

Google nos tiene acostumbrados a implementar APIs muy sencillas de usar, y en este caso no podía ser menos. Para demostrarlo, vamos a crear una página web con un sencillo traductor en Javascript, comentando paso por paso lo que hay que hacer para que podáis adaptarlo a vuestras necesidades.

Paso 1: Incluir el API

La inclusión de las funciones necesarias para realizar la traducción es muy sencilla. Basta con incluir el siguiente código, por ejemplo, en la sección HEAD de la página:
  <script type="text/javascript"
src="http://www.google.com/jsapi">
</script>
<script type="text/javascript">
google.load("language", "1");
</script>
 
El primer bloque descarga a cliente la librería javascript Ajax API Loader, el cargador genérico de librerías Ajax utilizado por Google. Éste se usa en el segundo bloque script para cargar, llamando a la función google.load el API "language" (traductor), en su versión 1 (el segundo parámetro).

Paso 2: Creamos el interfaz

Nuestro traductor será realmente simple. Además, vamos a contemplar un pequeño subconjunto de los idiomas permitidos para no complicar mucho el código, aunque podéis añadir todos los que consideréis necesarios.

El resultado será como el mostrado en la siguiente imagen.

Interfaz del traductor

El código fuente completo lo encontraréis al final del post, por lo que no voy a repetirlo aquí. Simplemente indicar que tendremos un TextArea donde el usuario introducirá el texto a traducir, dos desplegables con los idiomas origen y destino de la traducción, y un botón que iniciará la acción a través del evento onclick. Por último, se reservará una zona en la que insertaremos el resultado de la traducción.

Ah, un detalle interesante: en el desplegable de idiomas de origen se ha creado un elemento en el desplegable "Auto", cuyo valor es un string vacío; esto indicará al motor de traducción que infiera el idioma a partir del texto enviado.

Paso 3: ¡Traducimos!

La pulsación del botón provocará la llamada a la función Onclick(), desde donde se realizará la traducción del texto introducido en el TextArea.

Como podréis observar en el código, en primer lugar obtendremos los valores de los distintos parámetros, el texto a traducir y los idiomas origen y destino, y lo introducimos en variables para facilitar su tratamiento.
  var text    = document.getElementById("text").value;
var srcLang = document.getElementById("srcLang").value;
var dstLang = document.getElementById("dstLang").value;
 
Acto seguido, realizamos la llamada al traductor. El primer parámetro será el texto a traducir, seguido de los idiomas (origen y destino), y por último se introduce la función callback que será invocada cuando finalice la operación; hay que tener en cuenta que la traducción es realizada a través de una llamada asíncrona a los servidores de Google:

google.language.translate(text, srcLang, dstLang, function(result)
{
if (!result.error)
{
var resultado = document.getElementById("result");
resultado.innerHTML = result.translation;
}
else alert(result.error.message);
}
);
 
Como podéis observar, y es quizás lo único extraño que tiene esta instrucción, el callback se ha definido como una función anónima definida en el espacio del mismo parámetro (podéis ver otro ejemplo de este tipo de funciones cuando explicaba cómo añadir funciones con parámetros al evento OnLoad).

Para los queráis jugar con esto directamente, ahí va el código listo para un copiar y pegar.

<html>
<head>
<title>Traductor</title>
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("language", "1");
</script>
</head>

<body>
<textarea id="text" rows="8" cols="40">Hi, how are you?</textarea>
<br />
<button onclick="onClick()">
Traducir</button>
Del idioma
<select id="srcLang">
<option value="">(Auto)</option>
<option value="es">Español</option>
<option value="en">Inglés</option>
<option value="fr">Francés</option>
</select>
Al
<select id="dstLang">
<option value="es">Español</option>
<option value="en">Inglés</option>
<option value="fr">Francés</option>
</select>
<h3>Traducción:</h3>
<div id="result">
(Introduce un texto)
</div>
</body>
<script type="text/javascript">
function onClick()
{
// obtenemos el texto y los idiomas origen y destino
var text = document.getElementById("text").value;
var srcLang = document.getElementById("srcLang").value;
var dstLang = document.getElementById("dstLang").value;

// llamada al traductor
google.language.translate(text, srcLang, dstLang, function(result)
{
if (!result.error)
{
var resultado = document.getElementById("result");
resultado.innerHTML = result.translation;
}
else alert(result.error.message);
}
);
}
</script>
</html>
 


Enlaces: Página oficial de documentación del API

Publicado en: www.variablenotfound.com.
lunes, 24 de marzo de 2008
Actualizado el 25/4/09:
Existe una versión de este post ampliada y actualizada a la versión 1.0 de ASP.NET MVC: ASP.NET MVC: trece preguntas básicas
Varios lectores y amigos me han hecho llegar algunas cuestiones sobre el nuevo ASP.Net MVC Framework, y en vez de responder de forma individual, creo que es más interesante realizar un post recopilatorio e intentar que las respuestas puedan ayudar a más desarrolladores. Aprovecho para añadir cuestiones de mi propia cosecha, esperando que también puedan aclarar algo.

<disclaimer>
Algunas de las respuestas podríamos considerarlas como beta, y pueden variar con el tiempo. Son opiniones, ideas y conjeturas sobre un producto nuevo y que todavía está en desarrollo, así que usadlas con precaución. ;-)
</disclaimer>

1. Empecemos desde el principio, ¿qué es MVC?

Aunque de forma algo simplista, podríamos definir MVC como un patrón arquitectural que describe una forma de desarrollar aplicaciones software separando los componentes en tres grupos (o capas):
  • El Modelo que contiene una representación de los datos que maneja el sistema, su lógica de negocio, y sus mecanismos de persistencia.
  • La Vista, o interfaz de usuario, que compone la información que se envía al cliente y los mecanismos interacción con éste.
  • El Controlador, que actúa como intermediario entre el Modelo y la Vista, gestionando el flujo de información entre ellos y las transformaciones para adaptar los datos a las necesidades de cada uno.
MVC son las siglas de Modelo-Vista-Controlador, y se trata de un modelo muy maduro y que ha demostrado su validez a lo largo de los años en todo tipo de aplicaciones.

Puedes encontrar más información en:

2. ¿Qué ventajas tiene el uso del patrón MVC?

Como siempre, esto de enumerar ventajas es algo subjetivo, por lo que puede que pienses que falta o sobra alguna (¡dímelo!). En un primer asalto, podríamos aportar las siguientes:
  • Clara separación entre interfaz, lógica de negocio y de presentación, que además provoca parte de las ventajas siguientes.
  • Sencillez para crear distintas representaciones de los mismos datos.
  • Facilidad para la realización de pruebas unitarias de los componentes, así como de aplicar desarrollo guiado por pruebas (TDD).
  • Reutilización de los componentes.
  • Simplicidad en el mantenimiento de los sistemas.
  • Facilidad para desarrollar prototipos rápidos.
  • Los desarrollos suelen ser más escalables.
Pero bueno, también se pueden citar algunos inconvenientes:
  • Tener que ceñirse a una estructura predefinida, lo que a veces puede incrementar la complejidad del sistema. Hay problemas que son más difíciles de resolver respetando el patrón MVC.
  • La curva de aprendizaje para los nuevos desarrolladores se estima mayor que la de modelos más simples como Webforms.
  • La distribución de componentes obliga a crear y mantener un mayor número de ficheros.

3. ¿Qué es ASP.Net MVC Framework?

Es un framework, un entorno de trabajo que está creando Microsoft, que nos ayudará a desarrollar aplicaciones que sigan la filosofía MVC sobre ASP.Net. Su versión final incluirá librerías (ensamblados), plantillas y herramientas que se integrarán en Visual Studio 2008. ScottGu, en su presentación del framework el pasado Octubre en las conferencias Alt.Net, ya adelantó las principales características, y puedes ampliar información en la página oficial.

Actualmente (marzo 2008) puede descargarse la Preview 2 del framework, e incluso su código fuente ha sido publicado en CodePlex. Aunque "de fábrica" no soporta las versiones Express de Visual Studio, en este mismo blog puedes encontrar algunas plantillas y ejemplos de ASP.NET MVC. También hay quien la ha echado a andar en Mono.

4. ¿Es el primer framework MVC creado para .Net?

No, ni el único. Existen multitud de frameworks MVC para ASP.Net, como MonoRail, Maverick.Net, ProMesh.Net y muchos otros.

5. Como desarrollador de aplicaciones web con ASP.Net, ¿me afectará la llegada de este framework?

No necesariamente. Puedes seguir desarrollando aplicaciones como hasta ahora, con Webforms. Si así lo decides, este nuevo framework no te afectará nada; simplemente, ignóralo.

De todas formas, ya que has leído hasta aquí, permíteme un consejo: aprende MVC framework. Después podrás decidir con conocimiento de causa si te conviene o no.

6. ¿Significa la aparición del framework MVC la muerte próxima de los Webforms de ASP.Net?

En absoluto. Son simplemente dos filosofías diferentes para conseguir lo mismo, ¡páginas web!.

La tecnología de Webforms es muy útil para asemejar el desarrollo de aplicaciones web a las de escritorio, ocultando la complejidad derivada del entorno desconectado y stateless (sin conservación de estado) del protocolo HTTP a base de complejos roundtrips, postbacks y viewstates, lo que nos permite crear de forma muy productiva formularios impresionantes y que el funcionamiento de nuestra aplicación esté guiado por eventos, como si estuvieramos programando Winforms.

Sin embargo, esta misma potencia a veces hace que las páginas sean pesadas y difícilmente mantenibles, y además se dificultan enormemente la realización de pruebas. Y por no hablar de comportamientos extraños cuando intentamos intervenir en el ciclo de vida de las páginas, por ejemplo para la carga y descarga de controles dinámicos.

ASP.Net MVC propone una forma distinta de trabajar, más cercana a la realidad del protocolo y, curiosamente, más parecida a cómo se hacía unos años atrás, cuando controlábamos cada byte que se enviaba al cliente. No existen, por tanto, conceptos como el mantenimiento del estado en el viewstate, ni el postback, ni nos valdrán los controles de servidor basados en estas características, la mayoría. Sin embargo, dado que el framework está creado sobre ASP.Net, será posible utilizar páginas maestras, codificar las vistas en un .aspx utilizando C# o VB.Net, usar los mecanismos de seguridad internos, control de caché, gestión de sesiones, localización, etc; además, seguro que en un futuro no demasiado lejano comenzarán a surgir miles de componentes o controles reutilizables que nos ayudarán a mejorar la productividad.

7. ¿Vale la pena pasarse a ASP.Net MVC o sigo usando Webforms?

Todavía lo estoy estudiando ;-). Hay muchos aspectos a valorar.

No hay que olvidar que los Webforms son una buena opción, tanto como lo han sido hasta ahora. Sobre todo si el equipo de desarrollo tiene ya experiencia creando aplicaciones con esta tecnología y se dispone de controles reutilizables propios o ajenos, deberíamos pensárnoslo antes de dar el salto a ASP.Net MVC. Tened en cuenta que la productividad, al menos inicialmente, va a caer.

Sin embargo, las ventajas de la arquitectura MVC y del propio framework descritas anteriormente son un buen aliciente para comenzar: testing, URLs amigables, separación de aspectos, mantenibilidad... Por otra parte, todavía es pronto para conocer el nivel de las herramientas de desarrollo (a nivel de IDE, librerías de controles, helpers) que aparecerán con la versión final, y las que surgirán desde la propia comunidad de desarrolladores, por lo que no es posible evaluar el impacto en la productividad que tendrá la adopción de esta nueva forma de trabajar.

Y, por cierto, si te preocupa el futuro de los Webforms, has de saber que Microsoft va a seguir dándoles soporte y mejorándolos, como no podía ser de otra forma. Por tanto, de momento no es necesario que bases tu decisión en esto.

8. ¿Se puede utilizar el ASP.Net Ajax con el framework MVC?

De momento parece que no, o al menos no de la forma en que se hace actualmente, dado que los controles de servidor (runat="server"), como el UpdatePanel, no están integrados en este modelo. De hecho, ya ni siquiera tienen sentido los formularios runat="server", por lo que menos aún los controles que dependían de éstos.

Se prevé que se creará un API específico para permitir desde cliente, mediante scripting, hacer llamadas a los controladores, y actualizar porciones de contenido de la página con el marcado que nos envíe la vista correspondiente. Pero esto son sólo conjeturas de momento, ya se irá aclarando conforme el producto se acerque a su versión final.

9. ¿Puedo usar Linq desarrollando aplicaciones con ASP.Net MVC framework?

Sí, de hecho se complementan a la perfección.

Por ejemplo, las clases del modelo podrán generarse de forma automática (y completa para aplicaciones relativamente simples) con los diseñadores visuales de LinqToSQL o LinqToEntities desde Visual Studio 2008 o de forma externa con herramientas como SQLMetal. Además, el controlador podrán utilizar expresiones de consulta para solicitar datos desde el modelo, o enviar datos actualizados usando las capacidades ORM de estas tecnologías.

10. ¿Será ASP.Net MVC framework software libre?

Pues claro que no ;-). Se podrá acceder al código fuente (de hecho, ya se puede), que será distribuido de la misma forma que el de .Net framework, pero no será software libre. Si buscas una solución open source, revisa la pregunta número 4.


Publicado en: http://www.variablenotfound.com/.
domingo, 23 de marzo de 2008
De todos es conocida la afición de Microsoft por poner nombres clave a sus productos durante la etapa de conceptualización y desarrollo, y la verdad es que tiene su gracia. Pero la verdad, a veces es difícil seguirle la pista a posts o conversaciones en foros donde hacen uso intensivo de ellas.

Por ejemplo, ¿recuerdas el nombre en clave de ASP.NET Ajax? ¿Y de Windows 95? ¿Y sabes que tecnología se esconde detrás de Whistler o de Avalon?

Por suerte, en la Wikipedia, que hay de todo, alguien se ha encargado de recoger, si no todos los Codenames, al menos muchos de ellos.

Enlace: List of Microsoft codenames

Publicado en: http://www.variablenotfound.com/.