Cambios en la renderización de controles de ASP.NET 4.0

En mi anterior post comentaba que ASP.NET 4.0 había cambiado la forma de renderizar sus controles Web nativos para hacerlos más compatibles con XHTML, y que esto podía causar algunos problemas con aplicaciones hechas en versiones anteriores y migradas a la actual. También mostraba la forma de solucionar el problema y forzar la generación de HTML compatible con ASP.NET 3.5.


Lo que no comentaba era qué cambios exactamente se producen en el renderizado de estos controles ahora en ASP.NET 4.0, así que lo comento a continuación:




  1. Todos los controles renderizan XHTML Strict 1.0
  2. Los controles de validación no renderizan estilos «inline» sino clases CSS.
  3. Deshabilitar controles que no sean de entrada de datos ya no produce por defecto controles con el aspecto deshabilitado (lo comentaba en la práctica en el post anterior)
  4. Algunos controles que usaban el atributo border=0 ya no lo hacen (por ejemplo tablas o imágenes)
  5. Los elementos <div> que se generan alrededor de los campos ocultos en el formulario del Web Form llevan un estilo CSS para poder controlar si queremos que se vean o no. Estos DIV se generan para que los input de tipo hidden estén contenidos en otros elementos y sean compatibles con XHTML.

En este último caso ahora se generan de la siguiente manera:



<div class=»aspNetHidden»>…</div>


De manera que podemos redefinir esa clase aspNetHidden para conseguir que no se vean o que se vean de alguna forma particular.


¡Espero que te sea útil!

Renderizar HTML compatible con ASP.NET 3.x para los controles Web en ASP.NET 4.0

ASP.NET 4.0 ha cambiado la forma de renderizar los controles Web. Ahora, para representarlos en las páginas resultantes, genera HTML que cumple con los estándares de la W3C. En concreto los controles de ASP.NET 4.0 Web Forms generan XHTML 1.0 Strict.


XHTML_tag
Viñeta por Gabriel Utasi


Esto es fantástico para la mayor parte de los casos, ya que nos ayudará a que nuestras aplicaciones con ASP.NET Web Forms se adapten más fácilmente a los estándares y los requisitos de accesibilidad. Sin embargo puede darnos más de un dolor de cabeza en caso de que estemos reusando código CSS o Javascript que hayamos hecho con una versión anterior. También podría trastocarnos algunos maquetados de páginas hechos con versiones anteriores de la plataforma.


Para poder volver al comportamiento anterior de ASP.NET 3.5 (en realidad 2.0) y poder elegir la forma de renderizar los controles y por tanto el tipo de HTML generado, los controles tienen una nueva propiedad llamada RenderingCompatibility. Sin embargo esta propiedad, aunque es pública y su «setter» es accesible, no se debe usar directamente, ya que la propia documentación MSDN en el enlace anterior te avisa de que «puede tener efectos impredecibles«. Además, generalmente no tendrá mucho sentido hacer que un control concreto se renderice de manera diferente al resto de los controles de la página.


Así que existe un nuevo ajuste en web.config que nos permite seleccionar si queremos que los controles se rendericen como ASP.NET 4.0 o ASP.NET 3.5: ControlRenderingCompatibilityVersion. En este atributo ajustamos el modo de renderizado y ASP.NET automáticamente se ocupa de asignar la propiedad anterior en todos los controles.


Existen dos posibles valores: 3.5 y 4.0 (el valor por defecto).


Si en nuestro web.config ponemos esto:

<system.web>
<pages controlRenderingCompatibilityVersion=»3.5″/>
</system.web>

conseguiremos que los controles se rendericen como en la versión anterior de ASP.NET.


Esto significa en realidad que se van a renderizar en función de lo que indiquemos en el atributo xhtmlConformance, del que ya he hablado en otras ocasiones en este blog. Con él podremos decidir si se genera XHTML Strict, XHTML Trqansitional (lo habitual) o código no conformante con XHTML (Legacy).


Si no establecemos la compatibilidad con 3.5, ASP.NET 4.0 hace caso omiso del atributo xhtmlConformance y siempre genera XHTML Strict.


Algunos cambios llamativos en el HTML de controles


Hay un ejemplo muy llamativo del cambio de renderizado de ASP.NET 4.0 y se refiere a los controles que se establecen como deshabilitados.


En ASP.NET 2.0 hasta 3.5, cuando se establece la propiedad Enabled de un control como False para deshabilitarlo, lo que se consigue es que la etiqueta o etiquetas HTML correspondientes se deshabiliten mediante el atributo disabled. Así, por ejemplo, si deshabilitamos un control Label, así:

<asp:Label id=»Label1″ runat=»server» Text=»Etiqueta» Enabled=»false»>

lo que obtenemos en el HTML es esto:

<span id=»Label1″ disabled=»disabled»>Etiqueta</span>

El problema es que en XHTML 1.1 define este atributo únicamente para los controles de entrada de datos en formularios, es decir, que el atributo sólo se le aplica a los elementos HTML de tipo INPUT, SELECT, BUTTON, TEXTAREA, OPTION y OPTGROUP, como indica el estándar.


¿Entonces cómo se representan ahora las otras etiquetas que estén deshabilitadas?. Pues en el caso de un Label así:

<span id=»Label1″ class=»aspNetDisabled»>Etiqueta</span>

Esa clase CSS, , no está definida en ninguna parte, pero podemos definirla nosotros mismos en nuestra hoja de estilos de la página  para darle el aspecto que deseemos al control. Pero claro, por defecto, no notaremos diferencia en el aspecto del mismo.


Si queremos cambiar el nombre de la clase CSS usando la nueva propiedad de los controles estándar llamada DisabledCssClass, que es una cadena de texto con el nombre del estilo CSS.


¡Espero que te sea útil!


Aprende .NET, Cursos on-line tutelados:
   ·
Desarrollo Web con ASP.NET 4.0 Web Forms (Tutelado por mi)
   · ASP.NET 4.0 Web Forms desde cero (Tutelado por mi)
   · Desarrollo Web con ASP.NET MVC 2
   · Silverlight 4.0 – Aplicaciones Ricas para Internet (RIA)
   · jQuery paso a paso para programadores ASP.NET
   · Visual Studio 2010 desde cero

Cómo crear un temporizador global en ASP.NET

metronomeLas páginas Web son objetos con un tiempo de vida corto: se llaman, se ejecutan en el servidor, se devuelve el resultado y mueren. Por lo tanto no tiene sentido colocar en ellas un objeto como un temporizador (el típico Timer que sí tenemos en un formulario de Windows).

La forma de atar un evento periódico a una página Web (por ejemplo para actualizar los contenidos de la misma) es siempre en en lado cliente, es decir, con JavaScript. Para facilitarnos la vida, las extensiones de ASP.NET AJAX incluyen un control Timer que podemos arrastrar sobre el formulario para forzar la actualización periódica de uno o más UpdatePanels que tengamos sobre el mismo.

Sin embargo, en principio, no tenemos forma de conseguir un temporizador en el servidor que se ejecute cada cierto tiempo para todos los usuarios de nuestra aplicación. ¿O sí?

Crear un temporizador para una aplicación Web

Dentro de las clases base de la plataforma .NET, dentro del espacio de nombres System.Timers, existe una clase especial llamada Timer que sirve para crear temporizadores globales y está orientado a entornos de servidor (para requerimientos menos estrictos también existe la clase System.Threading.Timer, que es completamente distinta y no se adapta tan bien a nuestro caso).

Podemos usar esta clase para crear un temporizador global que funcione permanentemente en nuestra aplicación Web. Para ello podemos usar Global.asax para inicializarlo o, mejor aún, crear un pequeño módulo temporizador que podamos añadir a voluntad a nuestra aplicación sin necesidad de cambiar el código. Es lo que vamos a hacer.

Para el ejemplo vamos a crear un nuevo módulo HTTP con C# que implemente, como ejemplo sencillo, un contador global que se incremente cada segundo por medio de un temporizador.

El código es el siguiente:

using System;
using System.Web;
using System.Timers;

/// 
/// Summary description for ModuloTemporizador
/// 
public class ModuloTemporizador : IHttpModule
{
    // Variable que guarda una referencia al Timer (la misma para todas las instancias del módulo)
    static Timer _timerGlobal = null;
    static HttpApplication _App;

    public void Init(HttpApplication context)
    {
        if (_timerGlobal == null)
        {
            //Inicializo el contador
            context.Application.Lock();
            context.Application["Contador"] = 0L;
            context.Application.UnLock();

            //Guardo la referencia a Application
            _App = context;

            //inicializo el Timer
            _timerGlobal = new Timer(1000);
            _timerGlobal.Elapsed += new ElapsedEventHandler(ProcesoPeriodico);
            _timerGlobal.Start();
            
        }
    }

    public void Dispose()
    {
        _timerGlobal = null;
    }

    /// 
    /// Aquí se procesa periódicamente el Timer
    /// 
    private static void ProcesoPeriodico(object source, ElapsedEventArgs e)
    {
        _App.Application.Lock();
        long contador = (long)_App.Application["Contador"];
        _App.Application["Contador"] = contador + 1;
        _App.Application.UnLock();
    }

}

Se trata de un modulo HTTP normal, que implementa como todos la interfaz IHttpModule. Declara dos variables estáticas (serían Shared en VB) que permiten guardar sendas referencias al temporizador y al objeto Application, que nos permitirá acceder a las propiedades del mismo.

En el evento de inicialización la primera parte es sólo para nuestro ejemplo. Inicializa una variable de aplicación (común a todos los usuarios) que utilizaremos como un contador para verificar que el temporizador funciona. En condiciones normales no haríamos nada similar, pero a efectos de este ejemplo bien nos vale.

Después se establece la variable estática_App para tener acceso al contexto de aplicación desde toda la clase, y poder manejarlo desde otros métodos.

La parte interesante es la de inicialización del Timer, aunque no tiene tampoco ninguna dificultad: se declara un Timer pasándole el intervalo en su constructor. En este caso se le pasan 1000 milisegundos, o sea, un segundo, de forma que el temporizador hará «Tick» cada segundo. Se establece un manejador para su evento Elapsed, que se llama automáticamente cada vez que pase el periodo establecido y es donde realmente llevaremos a cabo la tarea periódica. Finalmente Se inicia el temporizador llamando a su método Start().

En el manejador del evento podemos llevar a cabo cualquier  tarea periodica que necesitemos: comprobar unos valores y refrescarlos, verificar que haya nuevos datos en una cola, anotar una información de traza interna que necesitemos para la aplicación, etc… Cualquiera que sea tu necesidad. En este ejemplo simplemente aumentamos el valor del contador.

Es posible detener el temporizador llamando a su método Stop() o cambiar el intervalo de notificación modificando el valor de la propiedad Interval.

Probando el temporizador

Para probar el temporizador y verificar que funciona he creado una pequeña página Default.aspx que el único código que contiene es este:

<%= Application("Contador") %>

Con esto lo que hacemos es mostrar el valor del contador por pantalla.

Si lanzamos la aplicación y llamamos a Default.aspx, refrescando sus contenidos con F5 en el navegador cada pocos segundos veremos…. ¡que no funciona!

El motivo es que hemos creado el módulo pero no lo hemos registrado con ASP.NET y por lo tanto no se ha usado.

Para registrar el módulo y que entre en funcionamiento nuestro temporizador sólo es necesario incluir esto en nuestro web.config:

<configuration>
	<system.web>
           <httpModules>
              <add name="ModuloTemporizador" type="ModuloTemporizador"/>
           </httpModules>
	</system.web>
</configuration>

O bien, si estamos trabajando en el modo integrado de IIS 7.x, este equivalente en el web.config del raíz:

<configuration>
	<system.webServer>
           <modules>
              <add name="ModuloTemporizador" type="ModuloTemporizador"/>
           </modules>
	</system.webServer>
</configuration>

Con esto ya podemos lanzar de nuevo la aplicación. Ahora, si refrescamos la página, veremos que el contador va aumentando en una unidad cada segundo. Si se conectaran varios usuarios diferentes 8en diferentes sesiones) veremos que el contador se les actualiza del mismo modo, y que no se detiene aunque cerremos todas las sesiones, ya que sólo parará si llamamos a Stop() o si la aplicación se cierra.

Esto último es muy importante: nuestro temporizador sólo funcionará mientras la aplicación Web esté funcionando. Es decir, que no se trata de un temporizador que se ejecuta todo el tiempo, desde que arranca el servidor, sino que mientras no se reciba una primera llamada a la aplicación y por lo tanto esta se inicie tampoco se iniciará el temporizador. Si por cualquier motivo (reciclado del grupo de aplicaciones, descarga de la memoria porque no hay usuarios, etc..) la aplicación se detiene también lo hará el temporizador.

No obstante este método es muy interesante para ser utilizado con necesidades particulares sobre la disponibilidad de un evento periódico global en nuestras aplicaciones web.

He dejado el ejemplo para descarga aquí.

¡Espero que te resulte útil!

Aprende .NET, Cursos on-line tutelados:
   ·
Desarrollo Web con ASP.NET 4.0 Web Forms (Tutelado por mi)
   · ASP.NET 4.0 Web Forms desde cero (Tutelado por mi)
   · Desarrollo Web con ASP.NET MVC 2
   · Silverlight 4.0 – Aplicaciones Ricas para Internet (RIA)
   · jQuery paso a paso para programadores ASP.NET
   · Visual Studio 2010 desde cero

Herramienta Open Source para análisis de seguidores en Twitter con cuestiones técnicas interesantes

LogoEste es un proyecto personal en el que he estado trabajando durante los últimos meses en mis ratos libres (que son pocos). Lo empecé como un juego para desestresarme y no oxidarme en las lides de la programación. Pero al final he querido darle calidad profesional y me he enredado más de la cuenta añadiéndole posibilidades, puliendo la interfaz de usuario, añadiendo pequeños detalles técnicos complicados que seguramente no va a notar ningún usuario «normal», en el periodo de pruebas, etc…


Twitter Followers Monitor es una aplicación gratuita y Open Source. Como su propio nombre indica te permitirá monitorizar los seguidores de cualquier cuenta de Twitter, llevando un histórico de cambios y siendo notificado cuando se produzcan. Puedes monitorizar varias cuentas a la vez y no tienen porque ser cuentas tuyas, ya que no es necesario saberse las claves.


TFM_Main


El proyecto está hecho con Visual Studio 2010 y .NET 4.0, y usando el lenguaje C#. No utiliza ningún módulo componente externo, así que con la propia plataforma .NET es suficiente.


Está dividido en tres componentes principales:




  • TFMAPI: es una biblioteca de funciones implementada como DLL que incluye todas las funciones necesarias para el manejo de la API de Twitter, las excepciones y el procesamiento de JSON.


  • Tests: los tests sencillos de la biblioteca anterior. En modo Debug usa datos JSON simulados en archivos de disco (e incluyen ejemplos).


  • TwitterFollowersMonitor: la UI del programa, aunque tiene bastante código de lógica también en el procesamiento en segundo plano de los datos de followers (le falta un pelín de refactoring).

Desde el punto de vista técnico tiene algunas cosas interesantes: el manejo de la API de Twitter, el lanzamiento en segundo plano de procesos, la seriación y de-seriación de datos en formato JSON, el uso de clases propias para almacenamiento, el control de excepciones y uso de excepciones propias, el uso de genéricos, el uso de LINQ para comparar conjuntos, uso del área de notificación del sistema, enlazado a datos, notificaciones visuales, determinar si el usuario está o no logueado en el sistema, saber si está o no conectado a través de escritorio remoto, evitar que una aplicación se ejecute varias veces, comprobar si hay actualizaciones, las actualizaciones automáticas con ClickOnce, lanzar URLs desde etiquetas…


Muchas de estas cosas serán desconocidas para algunos y se puede aprender viendo el código. Le falta algo de refactoring, y además ten en cuenta que soy programador Web, no Windows, pero en conjunto creo que es un código interesante y con bastantes más detalles de lo que pudiera parecer a simple vista.


Por cierto, el programa lo he hecho en inglés y el código está totalmente comentado también en inglés, aunque eso no debería ser un problema para ningún programador.


Lo he colgado en la comunidad CodePlex y puedes encontrarlo en:


http://twitterfollowersmon.codeplex.com/


¡Espero que te resulte interesante!


Aprende .NET, Cursos on-line tutelados:
   ·
Desarrollo Web con ASP.NET 4.0 Web Forms (Tutelado por mi)
   · ASP.NET 4.0 Web Forms desde cero (Tutelado por mi)
   · Desarrollo Web con ASP.NET MVC 2
   · Silverlight 4.0 – Aplicaciones Ricas para Internet (RIA)
   · jQuery paso a paso para programadores ASP.NET
   · Visual Studio 2010 desde cero