Adzure, la nube gratuita soportada por publicidad

Microsoft es una compañía que nos tiene acostumbrados a giros extraños en sus políticas de comercialización y distribución de productos, y está claro que la nube no iba a permanecer ajena a ellos.

Windows AdzureHace un par de días, ante el asombro de los presentes, Fred Swarm (cloud manager para la región EMEA) anunció la próxima apertura de Adzure, la edición gratuita del servicio Windows Azure soportada por publicidad.

Esto supone una auténtica revolución en el mundo de los servicios en la nube, que pasan del tradicional enfoque pay-per-use hacia un modelo de negocio basado en los ingresos publicitarios. Es decir, serán los anunciantes los que soportarán los costes de mantener en funcionamiento los roles e instancias de nuestras aplicaciones en la nube, la ocupación en disco, transferencia, uso de CDN, etc., sólo a cambio de que dejemos que se inserten anuncios publicitarios en determinados puntos de nuestros sistemas.

A cambio, no tendremos restricción alguna en cuanto al número de procesadores, memoria, ni ocupación de la infraestructura del gigante de Redmond. Podemos utilizar todos los recursos que necesitemos, y de hecho, se anima a que así sea: si una aplicación web debe escalar de forma brutal es porque tiene muchos visitantes… y visitantes es igual a impactos publicitarios, por lo que sería el escenario ideal para todos.

Adzure insertando publicidad en el interior de imágenesUna de las cosas más curiosas de este servicio es precisamente que la inserción de la publicidad se realizará de forma automática, los desarrolladores no tendremos que hacer nada al respecto: simplemente, los anuncios aparecerán en puntos donde la plataforma considere oportuno.

Esto es posible gracias a la nueva tecnología AdInsight®, que se encarga de analizar nuestro software una vez lo hemos desplegado en Adzure e inyectar en ellos la lógica de generación de anuncios publicitarios. Está claro que este automatismo a veces puede provocar pequeñas intrusiones como la que veis en la captura de pantalla adjunta, pero estaréis de acuerdo en que es un precio bastante razonable teniendo en cuenta el valor y potencia de la infraestructura que estamos usando de forma gratuita 🙂

Según se desprende del documento de notas de la revisión, existen tres únicos puntos de inserción publicitaria automática:

  • las páginas web generadas por un WebRole podrán ser modificadas de forma automática para incluirle código de script para la generación de anuncios contextuales.
  • el servicio de almacenamiento blob para contenidos digitales (imágenes, html, PDF, PPTs, vídeos, etc.) podrá introducir contenidos publicitarios en el interior de estos archivos, aunque casi siempre de forma no intrusiva.
  • los mails enviados y recibidos a través del servicio Adzure Mail Connector®, el motor que hay por detrás de Hotmail, también llevarán un mensaje publicitario contextualizado a la temática del mensaje.

El resto de servicios en la nube (como el almacenamiento en tablas, SQL Server, queues, buses, etc., de momento están libres de publicidad y pueden ser utilizados libremente y sin restricciones

Los anuncios se seleccionan de forma automática teniendo en cuenta la temática de la aplicación, el contexto en el que se insertan, el perfil del usuario conectado, y varios factores más. Sin embargo, en lugar de ser gestionados por la plataforma Microsoft Advertising, han preferido llegar a un acuerdo con Google e integrar la inteligencia de marketing de Adsense, bastante depurada, certera y que tantas alegrías nos da a sus usuarios.

Pero, ¿y qué ocurre con los ingresos generados por publicidad en las aplicaciones desplegadas en Adzure? Pues una nueva sorpresa: Microsoft los compartirá con los desarrolladores o propietarios del sitio en una proporción del 40% al 60% dependiendo del tráfico. Es decir, no sólo no nos costará utilizar la infraestructura de Adzure, sino que además podemos ganar dinero con ello 🙂

Pues no sé qué os parecerá a ustedes, pero yo veo la idea interesantísima. Adzure permite el uso de todos los servicios de la nube de forma gratuita, lo que abre un campo enorme a pequeñas empresas y startups que necesitan disponer de la gran capacidad de la nube, pero sin incurrir en coste alguno, simplemente a cambio de permitir la inserción automática de estos anuncios publicitarios en sus servicios, lo cual en algunos escenarios no tiene por qué ser un problema grave; de hecho, Gmail lo hace y no nos quejamos demasiado 😉

Sitio web alojado en Adzure con publicidad. Pulsar para verlo "en vivo".Además, el hecho de que aspectos infraestructurales como los servidores, anchos de banda, seguridad, etc., pasen de ser un coste a una fuente de ingresos me parece una vuelta de tuerca absolutamente necesaria.

De hecho, ya he comenzado a migrar todos mis desarrollos a Adzure, y el resultado está bastante bien (podéis ver una captura en el lateral); sin tocar una línea de código, sólo desplegarlo en la nube, la publicidad insertada se integra perfectamente en los diseños e incluso diría que lo mejoran, y por no hablar de que en unos días ya he conseguido algunos centimillos que nunca vienen mal.

Por cierto, actualmente estos servicios están en fase de beta privada y sólo se puede acceder por invitación, pero tengo treinta invitaciones para repartir entre los lectores del blog que estén realmente interesados en probarlo. Simplemente poneos en contacto conmigo por la vía que os sea más cómoda (por ejemplo ésta) y os iré enviando la URL y password personal de acceso en riguroso orden de llegada.

Y si preferís esperar, el servicio se abrirá al público en general el próximo uno de abril.

 

 

[Actualizado 29/12]
Nota para despistados: obviamente la noticia no es real, se trata simplemente de una broma del Día de los Inocentes. Por tanto, lamento comunicaros a los (muchos) que estáis esperando una invitación que de momento no va a poder ser ;-P

 

Publicado en Variable not found.

ASP.NET MVC: establecer el foco en un control al cargar la página

ASP.NET MVCUno de los aspectos más criticados por los desarrolladores cuando comienzan a trabajar con ASP.NET MVC es el hecho de tener que volver a resolver problemas que estaban ya más que solucionados en Webforms.

Y uno de estos casos es un detallito muy simple pero útil: establecer el foco de edición en un control concreto al cargar una página. En Webforms era suficiente con asignar al atributo defaultFocus del tag <form> el nombre del control que nos interesara, y ya lo teníamos solucionado; ASP.NET MVC no trae ninguna solución “de serie” para conseguirlo, aunque, como veremos en este post, no es mucho más complicado que la alternativa Webforms una vez hemos preparado la infraestructura necesaria.

En líneas generales, la solución consiste en utilizar un pequeño script que, una vez cargada la página, mueva el foco hacia el control que nos interese. Por ejemplo, si quisiéramos que el campo con identificador “Nombre” obtenga el foco automáticamente, podríamos utilizar jQuery de la siguiente forma:

<script type="text/javascript">
    $(function () {
        $("#Nombre").focus();
    });
</script>

Aunque eficaz, es una solución demasiado trabajosa e introduce una dependencia en el código, difícilmente manejable, hacia el nombre del control. Si quisiéramos introducir este código en múltiples puntos de nuestra aplicación tendríamos que copiar y pegar en cada vista, y sustituir el id del control apropiado en cada caso, lo cual es bastante incómodo.

¿No podríamos mejorar esto un poco?

El helper SetFocusTo()

Una posible solución, realmente rápida de implementar, sería crear un helper personalizado, al que llamaremos SetFocusTo(), que genere el código por nosotros partiendo únicamente de la información de la propiedad a editar.

Y para evitar la dependencia hacia el nombre de la propiedad y hacerlo más flexible, incluso podríamos crear la versión fuertemente tipada del mismo, de forma que podamos utilizarlo de cualquiera de las siguientes formas:

// Usando el nombre de la propiedad:
@Html.SetFocusTo("Nombre")

// Usando la versión fuertemente tipada:
@Html.SetFocusTo(model=>model.Nombre)

El código del helper es el siguiente:

public static class HtmlHelpers
{
    public static MvcHtmlString SetFocusTo<TModel, TProperty>(
                    this HtmlHelper<TModel> html,
                    Expression<Func<TModel, TProperty>> expression)
    {
        var prop = ExpressionHelper.GetExpressionText(expression);
        return html.setFocusTo(prop);
    }

    public static MvcHtmlString SetFocusTo(this HtmlHelper html, 
                                           string propertyName)
    {
        var prop = ExpressionHelper.GetExpressionText(propertyName);
        return html.setFocusTo(prop);
    }

    private static MvcHtmlString setFocusTo(this HtmlHelper html, 
                                            string property)
    {
        string id = html.ViewData.TemplateInfo.GetFullHtmlFieldId(property);
        var script = "<script type='text/javascript'>" +
                        "$(function() {" +
                            "$('#" + id + "').focus();" +
                        "});" +
                        "</script>";
        return MvcHtmlString.Create(script);
    }

}

Recordad que para que estos helpers estén visible en las vistas y podáis usarlos normalmente, debéis incluir el espacio de nombres en el que están definidos bien sea añadiendo una directiva @using en la vista, o bien en la sección <namespaces> del archivo web.config que encontraréis en la carpeta /Views (o en la del área correspondiente).

¡Y eso es todo! De esta forma ya volvemos a disponer de la posibilidad de establecer el foco por defecto sobre un control de forma muy rápida, compacta, y cómoda de utilizar.

Publicación original (14-dic-2011): http://www.variablenotfound.com/2011/12/aspnet-mvc-establecer-el-foco-en-un.html

Mamá, ¿de dónde vienen los metadatos?

ASPNETMVCEn ASP.NET MVC normalmente utilizamos atributos para aportar información adicional a las propiedades del Modelo, incluyendo detalles como su descripción textual, formato de presentación, tipo de datos, etc. Esta información puede ser utilizada desde la capa vista para generar etiquetas, editores y, en algunos casos, incluso lógica de edición o presentación en la página.

Sin embargo, los atributos en el propio código de la clase no son la única vía para especificar metadatos en el framework. En este post veremos cómo extender el framework para crear nuevas vías para especificar esta información.

1. Proveedores de metadatos

Como decíamos, ASP.NET MVC viene de fábrica con componentes que nos permiten introducir anotaciones directamente sobre las propiedades de las clases que manejamos. En el siguiente ejemplo podemos ver una entidad en la que se están introduciendo metadatos según este mecanismo:
public class Friend
{
    [Required]
    [Display(Name="Full name")]
    public string FullName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    [Display(Name = "Email address")]
    public string EmailAddress { get; set; }

    [Required]
    [DataType(DataType.Url)]
    [Display(Name = "Blog url")]
    public string BlogUrl { get; set; }

    [Display(Name="Birth year")]
    public int BirthYear { get; set; }
}
Cuando el framework necesita obtener los metadatos relativos a una clase, utiliza un metadata provider, un componente que se encarga de obtener los metadatos desde donde se encuentren definidos. El proveedor usado por defecto se llama DataAnnotationsModelMetadataProvider, y es el responsable de leer los atributos desde la definición de la clase, pero podemos sustituirlo fácilmente por otro proveedor que obtenga los metadatos desde otros orígenes, como archivos de configuración, bases de datos, o simplemente introducir lógica durante la generación de los mismos.

ModelMetadataSea cual sea su origen, los metadatos siempre se representan como objetos del tipo ModelMetadata, cuya estructura podéis ver a la derecha. Los providers deben incluir la lógica para obtener los metadatos desde donde corresponda, pero siempre retornarán objetos ModelMetadata, en los que, entre otra información, podemos encontrar los siguientes datos:

  • descripción del elemento,
  • cadena de formato cuando es visualizado,
  • tipo de datos que contiene (emails, urls, fechas, horas, etc.),
  • orden en el que debe aparecer la propiedad si se generan interfaces de edición o visualización de la entidad,
  • representación textual para los nulos,
  • si el dato es obligatorio, o de sólo lectura,
  • si debe ser mostrado en edición, o en visualización,
  • la plantilla de edición o visualización que debe utilizarse,
  • … y muchos más. Podéis consultar la referencia completa en MSDN.
Es importante tener en cuenta que el proveedor es invocado una vez para obtener los metadatos de la clase en sí, y otra vez por cada una de sus propiedades.

¿Y cómo determina el framework MVC qué proveedor de metadatos utilizar?

En primer lugar, intenta utilizar el dependency resolver para obtener una instancia de un tipo que implemente ModelMetadataProvider , que es la clase base para todos los proveedores. Este punto de extensión permite definir un proveedor personalizado muy fácilmente, y sobre todo si utilizamos contenedores IoC.

Si no ha sido posible obtener un proveedor desde el dependency resolver, el framework utilizará el establecido en la propiedad ModelMetadataProviders.Current. Por defecto, esa propiedad contiene una un objeto de la clase DataAnnotationsModelMetadataProvider, pero podemos sustituirlo por cualquier otro descendiente de ModelMetadataProvider .

Por tanto, para crear un proveedor personalizado de metadatos, basta con:

  • crear una clase descendiente de ModelMetadataProvider . Por comodidad, usaremos normalmente como base algunos de los siguientes tipos, más concretos:
    • DataAnnotationsModelMetadataProvider, si lo que pretendemos es extender el sistema por defecto, basado en la captura de metadatos desde las anotaciones (atributos) de la clase.
    • AssociatedMetadataProvider, si lo que queremos es saltarnos por completo la obtención de metadatos desde la propia clase e implementar otros mecanismos.
  • indicar al framework que debe utilizar nuestro nuevo proveedor, que podemos hacerlo:
    • o bien usando el dependency resolver,
    • o bien estableciendo una instancia del nuevo provider en ModelMetadataProviders.Current.
Pero mejor veámoslo con un ejemplo…

2. Creando un metadata provider

Vamos a implementar un proveedor de metadatos sencillo con objeto de que podáis entender su funcionamiento.

Como sabéis, al mostrar en una vista las etiquetas (labels) asociadas a una propiedad del Modelo, el texto que aparece es obtenido desde los metadatos de la entidad, desde el atributo Display o DisplayName (en ese orden); en caso de no existir, se asume como descripción el nombre de la propiedad.

Pues bien, nuestro objetivo es conseguir generar de forma automática estas las descripciones (DisplayName) de cada campo partiendo del nombre de la propiedad, y teniendo en cuenta el “camel casing”, de forma que podremos ahorrarnos el teclear esta descripción en muchos casos. Por ejemplo, a una propiedad que se llame FullName se le asociará automáticamente la descripción “Full Name”, o EmailAddress se describirá como “Email Address”. De esta forma la entidad anterior podremos simplificarla un poco:Resultado de EditorForModel() con la entidad Friend

public class Friend
{
    [Required]
    public string FullName { get; set; }

    [Required]
    [DataType(DataType.EmailAddress)]
    public string EmailAddress { get; set; }

    [Required]
    [DataType(DataType.Url)]
    public string BlogUrl { get; set; }

    public int BirthYear { get; set; }
}
Fijaos que hemos eliminado los atributos [Display], y el resultado en ejecución de un editor de esta entidad se mostrará como en la captura de pantalla lateral, donde las etiquetas de cada campo han sido generadas automáticamente.

Para ello, dado que queremos conservar el comportamiento del proveedor por defecto DataAnnotationsModelMetadataProvider, lo extenderemos y añadiremos la lógica deseada a su método CreateMetadata(), que es el invocado para obtener los metadatos de la entidad y cada una de las propiedades:

public class DisplayNameModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
            IEnumerable<Attribute> attributes, Type containerType,
            Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var metadata = base.CreateMetadata(attributes, containerType,
                                            modelAccessor, modelType, propertyName);
 
        if (metadata.PropertyName != null && metadata.DisplayName == null)
        {
            metadata.DisplayName = splitCamelCase(metadata.PropertyName);
        }
 
        return metadata;
    }
 
    static string splitCamelCase(string input)
    {
        return Regex.Replace(input, "([A-Z])", " $1", 
            System.Text.RegularExpressions.RegexOptions.Compiled).Trim();
    }
}
La implementación del método CreateMetadata() no es nada del otro mundo:
  • En primer lugar, llamamos a la clase antecesora para obtener los metadatos a partir de las anotaciones del modelo.
  • A continuación, si no se ha obtenido ningún valor de metadatos para el DisplayName, y siempre que se esté evaluando una propiedad, la establecemos, generándola mediante el método splitCamelCase().
  • El método splitCamelCase() no tiene mucho misterio (bueno, sí, usa expresiones regulares ;-)), y lo único que hace es buscar las letras mayúsculas e insertar delante de ellas un espacio. Es algo tosco, pero me vale para no desviar la atención del post a este detalle sin importancia (y por cierto, el mérito de este método no es mío, sino de Jon Galloway).
Y esto es todo. Ahora vamos a registrar el proveedor para el framework pueda utilizarlo, y veremos cómo hacerlo de las dos formas que he comentado antes: de forma directa, y usando el dependency resolver.

2.1. Registro del proveedor directamente

La fórmula más rápida y sencilla consiste en establecer directamente una instancia del nuevo proveedor en la propiedad ModelMetadataProviders.Current, durante la inicialización de la aplicación, por ejemplo así:
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
 
        ModelMetadataProviders.Current = new DisplayNameModelMetadataProvider();
 
        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);
    }
Esto es todo lo que necesitamos hacer para que nuestro flamante proveedor entre en funcionamiento.

2.2. Registro del proveedor usando el dependency resolver

Si estáis utilizando un contenedor de IoC, quizás sea más coherente introducir la resolución de este proveedor en el mismo.

Cuando el framework intenta obtener el proveedor de metadatos actual, antes de nada intenta localizarlo utilizando el dependency resolver. Si estamos utilizando un contenedor IoC como Unity o StructureMap, podemos utilizarlos para gestionar esta dependencia, asociando la clase abstracta ModelMetadataProvider al tipo concreto DisplayNameModelMetadataProvider.

Por ejemplo, en el caso de Unity, lo más sencillo es instalar el paquete Unity.MVC3 desde Nuget, y ya simplemente tendríamos que incluir la siguiente línea en el registro de tipos (en el archivo bootstrapper.cs):

    private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();
        container.RegisterType<ModelMetadataProvider, DisplayNameModelMetadataProvider>();
        container.RegisterControllers();
        return container;
    }
Una vez registrado el provider, sea directamente o mediante este último mecanismo, el sistema obtendrá los metadatos desde éste. Así, tendríamos el siguiente resultado:

Clase del Modelo Vista Resultado
public class Friend
{
 [Required]
 public string FullName { get; set; }

 [Required]
 [DataType(DataType.EmailAddress)]
 public string EmailAddress 
               { get; set; }
 [Required]
 [DataType(DataType.Url)]
 public string BlogUrl { get; set; }
 
 public int BirthYear { get; set; }
}

@using (Html.BeginForm())
{
    @Html.EditorForModel()
 
    <div>
        <input type="submit" />
    </div>
}
image
Puedes descargar el proyecto de ejemplo (VS2010 + MVC 3) desde mi Skydrive.

En definitiva, en este post hemos visto que en ASP.NET MVC los metadatos no proceden de una ubicación fija, sino que son obtenidos a través de un proveedor configurable. Esto nos permite modificar el comportamiento por defecto del framework y adaptarlo a nuestras necesidades, generarlos de forma dinámica, como en el ejemplo que hemos visto, u obtenerlo desde algún almacén de persistencia (como podría ser un archivo de configuración o una bases de datos), y siempre de forma muy sencilla aprovechando la magnífica extensibilidad del marco de trabajo 🙂

Publicación original (29-11-2011): http://www.variablenotfound.com/2011/11/mama-de-donde-vienen-los-metadatos.html
Tip: ¿todavía no conoces la selección de enlaces interesantes de Variable not found?

 

ASP.NET MVC: Introducir lógica personalizada al detectar errores de validación en cliente

ASP.NET MVCEl sistema de validación en cliente de ASP.NET MVC, como sabemos basado en jQuery validate, es el encargado de mostrar u ocultar los mensajes de error asociados a cada campo conforme va comprobando su validez.

Los mensajes de error asociados a cada validador son almacenados inicialmente en atributos data-val-* sobre el control a comprobar, y cuando se detecta un problema de validación, son mostrados copiando su contenido al interior de la etiqueta <span> que el helper Html.ValidationMessage() habrá generado sobre la página.

Sin embargo, al hilo de una consulta reciente en los foros de ASP.NET MVC en MSDN, perfectamente contestada por el amigo Eduard Tomás, pensé que realmente tenemos poco control sobre cómo se muestran estos errores, así que me he puesto un rato a ver cómo podíamos conseguir introducir lógica personalizada en este punto aprovechando la flexibilidad que ofrece jQuery validate 1.9.

Salvo por la escasez de documentación de este componente, tomar el control en el momento de mostrar los mensajes de error es bastante sencillo. Basta con establecer una función en la propiedad showErrors de los settings del plugin, cosa que podemos hacer con el siguiente script de inicialización:

<script type="text/javascript">
    $(function () {
        var settings = $.data($('form')[0], 'validator').settings;
        settings.showErrors = function (errorMap, errorList) {
            // Aquí el código personalizado:
            [...]

            // Y si nos interesa, finalmente podemos
            // ejecutar el comportamiento por defecto

            this.defaultShowErrors();
        };
    });
</script>

(Por simplificar, estamos asumiendo que en el formulario hay un único tag <form>, que es el que capturamos con el selector).

La función showErrors() recibe dos parámetros. El primero es un “mapa” donde asociamos a cada clave (nombre del campo) el mensaje de error que tenga asociado. Así, por ejemplo, el valor de errorMap.Nombre será nulo si el campo “Nombre” del formulario no tiene ningún error (ha validado correctamente), o el texto del error en caso contrario.

En el segundo parámetro de la función encontraremos un array con los errores a mostrar. En cada elemento tendremos disponible la propiedad element, desde la que podemos acceder al control que ha generado el error, y message, donde podemos consultar o establecer la descripción del mismo.

Es importante tener en cuenta que la función showErrors() es invocada con mucha frecuencia durante el proceso de edición (pérdida de foco, obtención de foco, pulsación de teclas…), por lo que desde el punto de vista de la usabilidad no tiene demasiado sentido introducir en ella procesos bloqueantes (como puede ser un alert()) o demasiado largos en el tiempo, para evitar que se solapen.

Por ejemplo, en el siguiente código utilizamos el efecto “highlight” de jQuery UI para resaltar con un rápido destello el elemento en el que se ha detectado un error:

    settings.showErrors = function (errorMap, errorList) {
        for (var i = 0; i < errorList.length; i++) {
            var error = errorList[i];
            // error.element es el elemento que ha provocado el error
            $(error.element).effect("highlight", { times: 1 }, 100);
        }
        this.defaultShowErrors();
    };

En fin, algo no demasiado útil ;-P, pero interesante en cualquier caso para profundizar un poco en los misterios e interioridades de jQuery validate.

Publicación original (22/11/2011): http://www.variablenotfound.com/2011/11/aspnet-mvc-introducir-logica.html
Tip: ¿todavía no conoces la selección de enlaces interesantes de Variable not found?