lunes, septiembre 14, 2009

Web Scheduled Tasks en ASP.NET 2.0, 3.0, 3.5 y MVC

¿Cómo hacer para automatizar tareas en nuestro sitio Web si no tenemos acceso al servidor ni a los Scheduled Tasks?

Omar Al Zabir nos ofrece una solución muy creativa: utilizar el evento que genera un objeto al ser removido del caché. Aquí la solución de Omar.

Tomando la solución propuesta pero intentando convertirla en lo más portable y menos invasiva posible desarrolle el Web Scheduled Tasks para ASP.NET 2.0 o superior. Funciona también con MVC.

Cómo funciona Web Scheduled Tasks

Web Scheduled Tasks se inicia en el Application_Start del global.asax y crea una lista de objetos IScheduleable obteniendo los datos del web.config.

En el web.config se indica cada cuanto tiempo el Web Scheduled Tasks llamará a las tareas y lo único que les proveerá son los objetos Application y Cache ya que de otra forma no estarían disponibles. El Resto depende de la tarea: cuando ejecutarse, cómo controlar si ya se está ejecutando, log de errores, etc.

Las tareas se ejecutarán en un thread que no estará vinculado con un request de un usuario por lo que no se puede utilizar cosas como HttpContext.Current o Server.MapPath.

Implementar Web Scheduled Tasks en 4 pasos

Paso 1: copiar  WebScheduledTasks.dll en la carpeta BIN de nuestra Aplicación Web.

Paso 2: crear las clases que implementen IScheduleable. La interfaz es muy sencilla con un método y dos propiedades.

IScheduleable

El método Run recibe el objeto Application y el objeto Cache ya que de otra forma serían inaccesibles.

Paso 3: configurar Web Scheduled Tasks a través del web.config. Para hacer esto utilicé el muy buen tutorial Creating Custom Configuration Sections in Web.config using .NET 2.0.

Son dos bloques. El primero hay que agregarlo dentro de <configSections> y define la nueva sección del Web.config y la clase que lo controla. El segundo va dentro de <configuration> y son los settings propios de Web Secheduled Tasks. El primer seteo es el intervalo que define cada cuantos minutos el sistema revisará las tareas para ejecutarlas.

web.config

Dentro de <tasks> están definidos los objetos que deben ejecutarse periódicamente. Debe colocarse el AssemblyQualifiedName, de otra forma no sabrá como instanciarlo. El AssemblyQualifiedName de mi tarea de ejemplo es "ActualizaHoraTask, App_Code.owmojsxy, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null". Si no saben como armarlo, pueden ejecutar esto: Response.Write((new Objeto()).GetType.AssemblyQualifiedName).

Paso 4: modificar el Global.asax. Simplemente debemos agregar la siguiente línea al evento Application_Start: bd.WebScheduledTasks.Scheduler.RunTimer();

globalasax

Cómo saber el estado de Web Scheduled Tasks

Scheduler expone la propiedad “Status” que devuelve un XML con el estado de Web Scheduled Tasks y las tareas.

En en XML se puede ver:

  • StartTime: fecha y hora en que se inicializó Web Scheduled Tasks
  • Interval: definido en el Web.config
  • LastTickTime: hora a la que se ejecutó por última vez
  • CacheTimerExist: muestra si existe el objeto en Cache que permite que todo funcione.
  • LastError: en “object” veremos el objeto que generó el último error y en “error” su descripción.
  • ScheduledTasks: veremos la lista de los objetos que invocará el sistema.

Web Scheduled Tasks Status

Además de Status, Scheduler expone el método “ScheduleTick” que nos permite, tal vez desde algún administrador, ejecutar las tareas programadas manualmente. En realidad lo que lograremos es “despertar” a Web Scheduled Tasks para que revise cuales tareas deben ser ejecutadas.

Descargar Web Scheduled Tasks

Pueden descargar:

Espero que les sea útil. Cualquier sugerencia, corrección, o aporte será más que bienvenido.

lunes, septiembre 07, 2009

Includes en ASP.NET MVC

De pronto me surgió la necesidad de usar INCLUDES en el sitio que estoy creando en ASP.NET y MVC. Como siempre fui a Google pero esta vez no encontré ninguna respuesta satisfactoria (alguno recomendó hacer un Html helper para leer el contenido de un archivo).

Alguien podría preguntar cual es la necesidad de usar Includes teniendo tantas otras alternativas. En mi caso, tengo un proceso que genera HTMLs estáticos y necesito mostrarlos en una "caja" en el sitio.

Luego de algunas pruebas, estas son las mejores formas, según mi criterio, de usar Includes en ASP.NET y MVC.

Los includes tradicionales siguen funcionando

En principio los Includes tradicionales de ASP siguen funcionando, de modo que podemos usar:
<!--#include virtual="/includes/pagina.htm"-->
para incluír un html a partir del root. También podemos usar
<!--#include virtual="../includes/pagina.htm"-->
para incluir un html en forma relativa a donde "estamos parados".

Esto funciona incluso si el TAG Include se encuentra dentro de un Partial View. El inconveniente es el de siempre: no podemos usar variables para definir cual archivos queremos incluir. Es decir, no podemos hacer esto:
<!--#include virtual="../includes/<%= nombreArchivo %>"-->
ya que el TAG include se interpretará antes que ASP.NET (aún con MVC donde todo pasa por ASP.NET).

Includes dinámicos

La forma que encontré para lograr "Includes dinámicos" es usar la sentencia
Html.RenderPartial("PartialView")
La única restricción es que el archivo debe tener extensión .ascx (o aspx) pero no necesita la cabecera que lo define como Partial View si guardamos el archivo en la carpeta /Views/Shared. Es decir, podemos tomar una HTML, le cambiamos la extensión y lo incluimos con Html.RenderPartial.

En mi caso, el proceso que genera el HTML, ahora lo graba a disco con la extensión .ascx

domingo, marzo 29, 2009

Mostrar AdSense sólo cuando el usuario viene de Google en ASP.NET

Es bastante común hoy en día encontrarnos con sitios que muestran publicidad de AdSense sólo a los usuarios que llegan a través de Google.

Por eso se me ocurrió hacer esto mismo pero de la forma más sencilla posible. Nada de estilo refinado en este caso, simplemente lo más fácil de implementar.

Así nació este User WebControl llamado refererAdSense contenido todo en un solo archivo .ascx. Seguramente el código puede ser mejorado o escrito con un poco más de estilo, sin embargo esto es lo que hice:

El WebControl comienza con una propiedad “AdPosition” que usaremos para identificar el código de AdSense que se debe mostrar. Un método booleano “UserFromGoogle” que devuelve true si encuentra la cadena “.google.” en el referer del request.

Por último, un simple SWITCH donde pondremos todos los códigos AdSense de nuestro sitio.

Para poder usar este User WebControl, simplemente lo copiamos en una carpeta (por ejemplo “/controls”) y, donde queremos la publicidad ponemos el tag “register” al principio de la página:

<%@ Register Src="~/controls/refererAdSense.ascx" TagName="refererAdSense" TagPrefix="rad" %>

Y finalmente ponemos el TAG correspondiente donde queremos la publicidad de AdSense:

<rad:refererAdSense AdPosition="topBanner" runat="server" />

Como valor de la propiedad “AdPosition” ponemos el nombre que identifica al bloque de AdSense del archivo .ascx.

Les dejo el refererAdSense.asxc para que lo bajen.

miércoles, febrero 04, 2009

Simulando streaming de video Flash FLV con ASP.NET

Esta solución permite reproducir video Flash FLV tal como lo hace YouTube.com de forma que podemos adelantar el video aún cuando no se haya descargado la parte que queremos ver.

La verdadera solución se encuentra en kfra de donde podremos descargar la solución tanto para .NET 1.1 como 2.0.

Pero para los que no podemos hacer modificaciones en el servidor IIS o (como yo) son amantes de las soluciones sencillas, no intrusivas y contenidas en una sola página es que armé esta versión.

Se trata de una página ASPX llamada getFlv.aspx que simplemente copiamos en nuestro sitio web e invocamos desde Flash con 2 parametros:
- v: para el nombre del video. Si comienza con “/” será el path relativo al root del sitio. Si no comienza con “/” buscará a partir del lugar donde se encuentre esta página.
- start: para indicar el byte a partir del cual quieren reproducir el video. Si no le pasamos nada, entonces devolverá el video completo.

Ejemplos:
  • http://misitio.dominio.com/videos/getFlv.aspx?v=video.flv (simplemente traerá el video ubicado en la mísma carpeta que getFlv.aspx)
  • http://misitio.dominio.com/videos/getFlv.aspx?v=/video.flv (traerá el video desde el root del sitio)
  • http://misitio.dominio.com/videos/getFlv.aspx?v=nuevos/video.flv&start=580014 (traerá el video desde la carpeta "nuevos" ubicada en la misma carpeta que getFlv.aspx y lo entregará a partir del byte 580014)
Hay que tener en cuenta que esta página ASPX lo único que hace es devolver el video FLV a partir del byte indicado por parámetro. El resto dependerá del player.

En la el mismo post de kfra hay un player que pueden usar, pero si quieren desarrollar uno ustedes, deberán tener en cuenta que, para poder reproducir el video, deben pasar un start que coincida con un Key Frame. Para esto deben buscar en la metadata del streaming donde encontrarán dos arrays, Times y FilePositions. No todos los FLV contienen esta metadata y en estos casos deberán usar alguna aplicación para agregarla.

Aquí les dejo el link a getFlv.aspx.

Por supuesto que todo el crédito es de kfra. Yo sólo hice uso de la programación orientada al copy-paste.

Saludos

jueves, julio 31, 2008

Cambio

Desde hace más de cuatro años que estoy en una posición de gestión. Esto me ha alejado de la tarea de escribir código. Por este motivo es poco frecuente que encuentre algo para postear en este blog.

Sin embargo, desarrollar sitios Web no sólo es escribir código por lo que decidí seguir manteniendo este blog y actualizarlo con otro tipo de posts más relacionado con lo que estoy haciendo ahora.