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.

3 comentarios:

frank dijo...

Excelente y elegante!

Anónimo dijo...

Que Barbaro hermano esto me ayuda un buen..!! jejeje

Grax Saludos desde Ags,Mexico.

Anónimo dijo...

Pero en donde le digo que se ejecute a las 7 de la noche todos los días ?????????

yo tengo un método

public class MundoController : Controller
{
public ActionResult Index()
{
//Código.........
}
}

Como le digo que ejecute este index todos los días a las 7 de la noche ?????