Error con jQuery UI datepicker dentro de formulario en Safari

Escenario

Hace algunos días me encontré con un problema en Safari al establecer fechas con un datepicker de Metro UI que es el mismo que el que corresponde a jQuery UI datepicker. El problema se producía al seleccionar una fecha que, al realizarse la validación con jQuery.validation decía que era incorrecta al contrario que en el resto de navegadores (Internet Explorer, Microsoft Edge, Google Chrome*, Firefox y Opera). Además, parece que el error se reproducía en Google Chrome para Mac lo que hacía más complicado determinar cuál es el problema. Como se puede apreciar en la imagen, tiene problemas al establecer fechas predefinidas como en el campo “inicio” en el que he puesto la fecha actual (tanto desde el modelo como con JavaScript) y, en el campo “Vencimiento” la fecha seleccionada con el datepicker genera un error de validación “incomprensible”

Solución

La solución es sencilla aunque no me parece del todo correcta y pasa por saltarse la validación de los campos que estén relacionados con el datepicker con una simple instrucción que siempre devolverá “true” cuando se trate de una fecha.

jQuery.validator.methods[“date”] = function (value, element) { return true; }

 

Tiene algo de sentido si pensamos que la fecha está establecida por el propio datepicker y que no se debe permitir que se inserte una fecha manualmente, cosa que de forma automática ya cumple el datepicker, pero podría darse el caso de que sí que necesitemos realizar algún tipo de validación que nos estaríamos perdiendo por forzar que siempre devuelva “true”.

Explicación

Por lo que he investigado, Safari incluye algún tipo de tratamiento para las fechas que nos rompe nuestra validación y que, por lo tanto, nos generará un error de formato. Yendo un poco más allá, parece que en Mac esto mismo se reproduce para Google Chrome, cosa que me parece “inexplicable” cuando sobre Windows funciona correctamente.

¿Conoces alguna solución?

¿Conocéis algún workaround más elegante u óptimo? Abramos el debate pero adelanto que tengo preestablecido el lenguaje en el fichero web.config “es-ES” y en el propio datepicker “es”.

ASP.NET MVC | Cómo enviar modelo con JavaScript desde un formulario a una acción

Escenario

Supongamos que tenemos un formulario en una vista de una aplicación web realizada con ASP.MVC y necesitamos enviar los datos, que corresponden a un modelo de la aplicación, a nuestra acción del controlador. ¿Cómo realizamos esta tarea? Seguro que se nos ocurren ideas “liosas” para realizar esta operación pero generalmente optamos por lo más obvio que, además, no es óptimo ni flexible o no aprovechamos las facilidades que nos ofrece el ModelBinding.

Para explicar las posibilidades, quiero exponer las dos opciones que me he encontrado con más regularidad (por orden de veces que lo he visto) antes de exponer la que a mi parecer es la opción más óptima y os explicaré por qué.

Solución NO óptima 1

Lo que más he visto hacer, es lo más costoso y menos flexible que se podría hacer y no es otra solución que cambiar los parámetros de la acción del controlador por los campos del modelo y, en código JavaScript, recoger cada uno de esos campos por separados y mandarlos en los datos de la acción “Ajax”. Esto no es en ningún momento óptimo ni bueno aunque funcione porque no es nada flexible ante cambios con lo que si añadimos una nueva propiedad, tendremos que cambiar todo nuestro código para poder enviarla, recibirla y validarla.

Acción del controlador

  1. [HttpPost] 
  2. public JsonResult Create(string brand, string model, …) {  
  3.     try {  
  4.         if (string.IsNullOrEmpty(brand) || string.IsNullOrEmpty(model) || …) return false;  
  5.         var car = new Car {  
  6.             Brand = brand, Model = model, // …  
  7.         };  
  8.         car.Status = “Solicitados”;  
  9.         return Json(true);  
  10.     } catch {  
  11.         return Json(false);  
  12.     }  
  13. }  

     

    Código JavaScript

  14. $(‘#btn-sendForm’).click(function() {  
  15.     var car = {  
  16.         prop1: document.getElementById(‘brand’).value(),  
  17.         prop2: document.getElementById(‘model’).value(), // …  
  18.     }  
  19.     $.ajax({  
  20.         url: ‘@Url.Action(“ACTION”, “CONTROLLER”)’,  
  21.         type: ‘POST’,  
  22.         data: item,  
  23.         success: function(result) {  
  24.             var modelStatus = $(‘.model-status’);  
  25.             if (result) modelStatus.text(“Estado: Enviado con éxito”);  
  26.             else modelStatus.text(“Estado: Enviado con error. Compruebe que ha rellenado todos los campos”);  
  27.         },  
  28.         error: function(jqXHR, textStatus, error) {  
  29.             $(‘.model-status’).text(“Estado: Error inesperado”);  
  30.         }  
  31.     });  
  32. });  

     

    Solución NO óptima 2

    A priori podría parecer que la solución pasaría por dejar el formulario con el parámetro del tipo del modelo y crearnos un objeto en JavaScript con las propiedades necesarias e ir recogiendo los valores uno por uno de los campos del formulario para posteriormente enviarlos en la acción “Ajax” como el código que explico a continuación. Esta opción está muy cerca de la óptima porque recibimos el modelo en la acción y la validación se la delegamos al ModelState, pero aún sigue sin ser flexible ya que, si añadimos un nuevo campo al formulario, tendríamos que añadir esa nueva propiedad al objeto JavaScript para poder enviarlo y, como sabemos, esto siempre puede llevar a olvidos y/o errores.

    Acción del controlador

  33. [HttpPost] 
  34. public JsonResult Create(Car car) {  
  35.     try {  
  36.         if (!ModelState.IsValid) return Json(false);  
  37.         car.Status = “Solicitados”;  
  38.         return Json(true);  
  39.     } catch {  
  40.         return Json(false);  
  41.     }  
  42. }  

     

    Código JavaScript

  43. $(‘#btn-sendForm’).click(function() {  
  44.     var car = {  
  45.         prop1: document.getElementById(‘brand’).value(),  
  46.         prop2: document.getElementById(‘model’).value(), // …  
  47.     }  
  48.     $.ajax({  
  49.         url: ‘@Url.Action(“ACTION”, “CONTROLLER”)’,  
  50.         type: ‘POST’,  
  51.         data: item,  
  52.         success: function(result) {  
  53.             var modelStatus = $(‘.model-status’);  
  54.             if (result) modelStatus.text(“Estado: Enviado con éxito”);  
  55.             else modelStatus.text(“Estado: Enviado con error. Compruebe que ha rellenado todos los campos”);  
  56.         },  
  57.         error: function(jqXHR, textStatus, error) {  
  58.             $(‘.model-status’).text(“Estado: Error inesperado”);  
  59.         }  
  60.     });  
  61. });  

     

    Solución ÓPTIMA

    Por último, vamos a ver la solución que a mi parecer es la óptima para estos casos. Lo que haremos, es tener la acción del controlador como en el caso anterior pero variaremos un poco el JavaScript para enviar todo el formulario de golpe. De esta forma, conseguimos que si tenemos que añadir un nuevo campo al formulario, no nos tengamos que preocupar cómo se envía ni cómo se recoge gracias al ModelBinding

    Acción del controlador

  62. [HttpPost] 
  63. public JsonResult Create(Car car) {  
  64.     try {  
  65.         if (!ModelState.IsValid) return Json(false);  
  66.         car.Status = “Solicitados”;  
  67.         return Json(true);  
  68.     } catch {  
  69.         return Json(false);  
  70.     }  
  71. }  

     

    Código JavaScript

  72. $(‘#btn-sendForm’).click(function() {  
  73.     var formContainer = $(‘#car-form’);  
  74.     $.ajax({  
  75.         url: ‘@Url.Action(“Create”, “Car”)’,  
  76.         type: ‘POST’,  
  77.         cache: false,  
  78.         data: formContainer.serialize(),  
  79.         success: function(result) {  
  80.             var modelStatus = $(‘.model-status’);  
  81.             if (result) modelStatus.text(“Estado: Enviado con éxito”);  
  82.             else modelStatus.text(“Estado: Enviado con error. Compruebe que ha rellenado todos los campos”);  
  83.         },  
  84.         error: function(jqXHR, textStatus, error) {  
  85.             $(‘.model-status’).text(“Estado: Error inesperado”);  
  86.         }  
  87.     });  
  88. });  

     

    Como podéis observar, lo que haremos será serializar el formulario completo dentro de la propiedad “data” de la acción “Ajax” con lo que estaremos enviando todos los campos del formulario y, una vez en la acción del controlador, gracias al ModelBinding, el parámetro del modelo, en este caso “Car car” se rellenará de forma automática con todos los valores que procedan, los validamos con el ModelState y hemos acabado. Esto es totalmente flexible a cambios y, por lo tanto, no nos dará dolores de cabeza cuando tengamos que hacer modificaciones en el formulario.

     

    Resumen

    Siempre debemos intentar buscar la solución más óptima y flexible para nuestros desarrollos porque en el futuro, cuando tengamos que mantener el código u otro se encargue de esa tarea, nos alegraremos de haber perdido un poco de tiempo en ello.

    Podéis descargaros una solución simple de ejemplo desde mi GitHub

Azure Webjobs | Envío de correo con SendGrid

Es bastante común que necesitemos enviar correos electrónicos desde nuestras aplicaciones web para notificar ciertas acciones realizadas por eso, hoy quiero compartir un ejemplo de cómo desarrollar un Azure Webjob que realice el envío de correos por medio de SendGrid que, dado que para los suscriptores de Microsoft Azure dispone de una opción gratuita que permite enviar hasta 25.000 correos al mes, es, desde mi punto de vista, la mejor opción.

Para ilustrar el ejemplo, detallaré paso a paso cómo configurar todo lo necesario para usar SendGrid desde un proyecto de consola que después se podrá publicar como Webjob asociado a una aplicación web (Web App) alojada en Microsoft Azure.

Crear el servicio de SendGrid desde la tienda de Microsoft Azure

En primer lugar debemos acceder a nuestra cuenta de Microsoft Azure y dirigirnos a la tienda de servicios donde buscaremos SendGrid. Una vez lo hayamos localizado, sólo tenemos que agregarlo y rellenar los datos correspondientes a su configuración.

Es muy importante que nos quedemos con el usuario y que recordemos la contraseña porque será lo que nos permita enviar el correo

Añadiendo la referencia a SendGrid en nuestro proyecto

Ahora que ya tenemos creado el servicio de SendGrid, debemos referenciar la API desde nuestro proyecto de consola que previamente habremos creado. Esto lo haremos desde el Administrador de paquetes de Nuget

 

Crear un correo

Ahora que ya tenemos el servicio y la referencia a la API, será muy sencillo crear y enviar correos tal y como se explica en la documentación de SendGrid

Lo primero que debemos hacer es generar el correo con los parámetros correspondientes tal y como muestro en el siguiente código

 


private static MailMessage CreateEmail()
{
    // Create the email object first, then add the properties.
	 var message = new MailMessage();
    // Add the message properties.
    message.From = new MailAddress("santiagoporras@santiagoporras.com");
    // Add multiple addresses to the To field.
    var recipients = @"Santiago Porras Rodríguez <demo1@gmail.com>,
                       Santiago Porras Rodríguez <demo2@gmail.com>,
                       Usuario Demo 1 <demo1@outlook.com>,
                       Usuario Demo 2 <demo2@outlook.com>";
    message.To.Add(recipients);
    message.Subject = "Testing the SendGrid Library";
    //Add the HTML and Text bodies
    var html = "<h1>¡santiagoporras.com próximamente!</h1><p>En breve estará disponible mi sitio web. No dudes en visitarlo</p>";
    var text = "¡santiagoporras.com próximamente!n En breve estará disponible mi sitio web. No dudes en visitarlo";
    message.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));
    message.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Html));
    return message;
}

 

Enviar un correo

El envío lo haremos por medio de SMTP mediante un simple código que establece las credenciales con las que estamos dados de alta en el servicio y que os dije que debíais recordar en el paso de creación del servicio.


private	static void SendEmail (string sgUsername, string sgPassword, MailMessage message)
{
    // Set credentials
    var credentials = new NetworkCredential(sgUsername, sgPassword);
    // Create SMTP cliente
    SmtpClient smtpClient = new SmtpClient("smtp.sendgrid.net", Convert.ToInt32(587));
    smtpClient.Credentials = credentials;
    // Send email
    smtpClient.Send(message);

}

Publicar como Webjob

Ahora debemos proceder a publicar este proyecto como Webjob de nuestra aplicación web tal y como os mostré en este artículo.

Ver estadísticas

Finalmente, podemos entrar en el sitio de estadísticas de SendGrid y ver cuál es el uso que estamos haciendo de este servicio.

Resumen

Como podéis comprobar, es muy sencillo crear el servicio, que nos permite el envío de hasta 25.000 correos de forma gratuita y, mediante su API, poder generarlos y enviarlos a los usuarios de nuestras aplicaciones web y espero que os sirva de ayuda. Podéis descargaros el código desde GitHub

ASP.NET 5 (vNext) | Conectando nuestro sitio ASP.NET 5 beta5+ con Azure Active Directory

Con las últimas actualizaciones Visual Studio y ASP.NET 5, ya es posible crear un sitio conectado a un directorio activo desde la creación de la plantilla del proyecto, cosa que veníamos echando de menos los que ya estábamos haciendo algunas cosas con esta nueva versión de ASP.NET aunque, como podremos observar, es una tarea bastante sencilla una vez la hayamos visto.

Para ilustrarlo, en este artículo haré una introducción sobre cómo crear nuestra aplicación conectada con Azure Active Directory y el código que pone nuestra plantilla para conectarse, hacer login y logout y ver que funciona correctamente publicada como Azure Web App. Podéis descargaros el ejemplo de GitHub.

Creando el proyecto

Lo primero es crear un proyecto ASP.NET 5 usando la plantilla de Visual Studio como se ve en la imagen y para ir ahorrando tiempo, marcamos la casilla de “Alojar en Azure” en una Web App con lo que directamente podremos publicar nuestro sitio web y hacer pruebas online.

Para conectar con el directorio activo, seleccionamos la opción “Cambiar autenticación” y realizamos los siguientes pasos:

  1. Marcar la opción “Cuentas de trabajo o estudiante”
  2. Seleccionar el tipo de Directorio Activo con el que vamos a conectar, que en nuestro ejemplo será “Cloud – Single Organization”
  3. Indicar el dominio de nuestro directorio activo, en este caso XXXXX.onmicrosoft.com
  4. Si queremos hacer operaciones de lectura de datos del directorio activo, debemos marcar la opción “Leer datos del directorio”
  5. Aceptar

Desgranando el código

Al crear el proyecto directamente conectado con Azure Active Directory, automáticamente se ha generado código que hace que todo funcione pero debemos saber qué es y cómo funciona, así que vamos a ver qué se ha hecho.

Startup.cs

Abrimos el fichero Startup.cs que se encuentra en la raíz del proyecto y vemos código generado automáticamente en dos de los métodos de este fichero.

ConfigureServices(…)

Aquí podemos apreciar que se ha añadido código que nos permite la autenticación usando las cookies y después se configurar el acceso al directorio activo leyendo parámetros de configuración que en la creación del proyecto se generaron automáticamente en la Web App. Si no quisiéramos estos parámetros, tendríamos que configurarlos en el fichero config.json que se encuentra también en la raíz del proyecto.

  1. services.Configure < CookieAuthenticationOptions > (options => {  
  2.     options.AutomaticAuthentication = true;  
  3. });  
  4. services.Configure < OpenIdConnectAuthenticationOptions > (options => {  
  5.     options.AutomaticAuthentication = true;  
  6.     options.ClientId = Configuration[“Authentication:AzureAd:ClientId”];  
  7.     options.Authority = Configuration[“Authentication:AzureAd:AADInstance”] + Configuration[“Authentication:AzureAd:TenantId”];  
  8.     options.PostLogoutRedirectUri = Configuration[“Authentication:AzureAd:PostLogoutRedirectUri”];  
  9.     options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;  
  10. });  

 

Configure

Vemos que en este método se ha añadido la inicialización de OpenId con la siguiente instrucción que establece el middleware de OpenId como el sistema encargado de la autenticación contra Azure Active Directory.

  1. // Add OpenIdConnect middleware so you can login using Azure AD.  
  2. app.UseOpenIdConnectAuthentication();  

 Como se puede observar, es todo muy sencillo ya que sólo hay que establecer los parámetros de conexión con nuestro Azure Active Directory e inicializar el middleware.  

AccountController.cs

Dentro de este controlador debe ir el código que interactúe con el usuario para realizar las tareas de autenticación que, en este caso, dado que se trata de un directorio activo, sólo incluirán el Login y el Logout. Por ello, de una forma muy sencilla, se establece que el login se realiza mediante el middleware de OpenId con una simple instrucción donde además se le puede especificar la Url de retorno que aconsejo modificar para que vuelva siempre a la página desde la que el usuario solicita la autenticación.

public IActionResult SignIn() {  
    return new ChallengeResult(OpenIdConnectAuthenticationDefaults.AuthenticationScheme, new AuthenticationProperties {  
        RedirectUri = “/”  
    });  
}  
public IActionResult SignOut() {  
    var callbackUrl = Url.Action(“SignOutCallback”“Account”, values: null, protocol: Request.Scheme);  
    Context.Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationScheme);  
    Context.Authentication.SignOut(OpenIdConnectAuthenticationDefaults.AuthenticationScheme, new AuthenticationProperties {  
        RedirectUri = callbackUrl  
    });  
    return new EmptyResult();  
}  
public IActionResult SignOutCallback() {  
    if (Context.User.Identity.IsAuthenticated) { // Redirect to home page if the user is authenticated.  
        return RedirectToAction(nameof(HomeController.Index), “Home”);  
    }  
    return View();  
}  

Como se puede observar, no hay nada muy complejo dado que de todo ello se encarga el middleware y sólo tenemos que indicar los parámetros y el comportamiento que deseamos.

Publicando en Azure

Cuando se haya creado el proyecto, ya estará preparado para publicar en Azure ya que, durante el proceso se ha creado la correspondiente Web App, con lo que sólo tendremos que hacer click con el botón derecho sobre el nombre del proyecto, y seleccionar “Publicar”.

Habrá que configurar correctamente los parámetros de la publicación, seleccionando la Web App correspondiente y, finalmente estableciendo las propiedades adecuadas para el directorio activo tal y como muestro en la imagen a continuación. Notad que aquí ya no es necesario establecer el directorio activo porque se ha generado de forma automática ese parámetro en la Web App.

 

Probando la aplicación

Finalmente, podemos probar la aplicación y comprobar cómo se nos solicita aprobar el acceso a nuestra cuenta de la aplicación asociada al directorio activo.

 

Resumen

Hemos visto lo sencillo que es conectarse a Azure Active Directory con la plantilla del proyecto de ASP.NET 5 beta5 pero, además, viendo el código también resultará muy sencillo lograrlo aunque no hayamos partido de esa plantilla ya que sólo tenemos que establecer los parámetros y determinar el comportamiento del middleware de OpenId.

Espero que os haya sido de utilidad y que aprovechéis al máximo las capacidades de ASP.NET 5 que será el nuevo estándar propuesto por Microsoft cuando vea la luz definitiva dentro de muy poco.

Enjoy coding!!

TLP Innova | Un año más en el mayor evento tecnológico de Canarias

Ayer se abrieron las puertas de la zona TLP Innova dentro de Tenerife Lan Party pero hoy comienza mi participación con TenerifeDev apoyando a los ponentes que hemos invitado a ilustrarnos y formarnos sobre algunas de las nuevas tecnologías de Microsoft.

Hoy jueves tendremos un taller sobre Xamarin.Forms impartido por el gran Josué Yeray Microsoft MVP Windows Platform Development y otro taller que impartirá Javier Suárez también Microsoft MVP Windows Platform Development.

10:00 – 13:00 | Taller: Xamarin.Forms, un código para unirlos a todos!

16:00 – 19:00 | Taller: Desarrolla para todos los dispositivos Microsoft con Windows 10

Mañana viernes, tendrá lugar el grueso de nuestra participación en esta edición de 2015 con 10 sesiones técnicas en las que participaré hablando de desarrollo web con ASP.NET y Visual Studio, así como el futuro que se nos viene encima de la mano de Microsoft. Entretanto, otros ponentes, de los que la mayor parte ha venido desde la península a este evento, hablarán sobre Movilidad, Marketing Mobile, Mobile Engagement, Azure, Machine Learning y Programación de Gadgets. No os podéis perder esta ocasión única de conocer a estos ponentes de talla internacional y lo que os pueden contar.

Ni qué decir que será una oportunidad inigualable para hacer “networking” con los ponentes y con el representante de Microsoft DX, Alejandro Campos Magencio, así que… preparad vuestras preguntas y no faltéis!!!

NOTA: No olvidéis registraros gratuitamente desde la web de TLP Innova http://tlp-tenerife.com/tlpinnova/agenda/mes/?tribe-bar-date=2015-07-13

GAPAND 2015 | Disfrutar de Andorra a ritmo de tecnología

El pasado 4 de julio estuve en Andorra para disfrutar de GAPAND 2015 donde tuve la oportunidad de participar como ponente junto a Adrián Díaz y compartir cartel con todo un elenco de ponentes de nivel “god” (todos ellos).

 

Ya el viaje a Andorra prometía con un viaje en coche junto a Adrián, Josué Yeray e Hilda donde no faltaron las anécdotas de las que se cuentan a los nietos. Finalmente pudimos llegar a nuestro destino preparados para lo que nos deparaba una apasionante jornada en la Universidad de Andorra con 3 tracks en paralelo y diversos talleres gracias a la GRAN ORGANIZACIÓN de Andorra_dot_net con LLUIS FRANCO a la cabeza (Nos quitamos el sombrero ante Lluis, exitazo!)

Adrián y yo teníamos una dura prueba a la que enfrentarnos ya que hablábamos tras Josue Yeray (Showman king) y antes de Bruno Capuano (Showman god), así que no podíamos dejar pasar la ocasión de ponernos el mono de Chinos mayores del reino y mostrar un completo repertorio de tecnologías Microsoft para escenificar nuestra demo de Machine Learning y Project Oxford. Por ello, montamos un sitio web con ASP.NET MVC5 alojado en una Web App de Azure, con tres WebJobs que consultaban y procesaban la información que alojamos en, cómo no, SharePoint Online de Office365. Aquí podéis ver las slides que usamos.

  

 

Finalmente, tras el evento disfrutamos de unas horas de networking muy gratificantes que, como siempre, nos unen y acercan aunque la distancia entre nuestras residencias sea grande.  

CEUS by Iberian SharePoint Conference 2015, rompiendo registros

Esta edición de CEUS by Iberian SharePoint Conference 2015 estaba marcada por la convergencia entre los dos mayores eventos de SharePoint en españa, CEUS que incluía la parte más orientada al negocio e Iberian SharePoint Conference que trataba la parte más técnica. El resultado ha sido un gran evento de dos días en el que rompimos todas las previsiones de asistencia y pudimos conocer todos los aspectos de SharePoint y de las tecnologías con las que se relaciona, Azure, Lync, Visual Studio, SQL Server, ALM,…

El primer día tuvieron lugar las keynotes a cargo de profesionales de Microsoft y los talleres técnicos, 6 en total, de los cuáles tuve el placer de impartir uno para poner mi granito de arena mostrando a un grupo de más personas de las previstas cómo aplicar Branding en SharePoint mediante un caso de uso con SharePoint Online en Office365. El resto de compañeros también tuvo gran éxito llenando sus salas y consiguiendo una alta valoración por parte de sus asistentes.

El segundo día, fue el más fuerte al tener 7 tracks en paralelo en los que participé en una mesa redonda de discusión sobre movilidad en SharePoint 2013 junto a Rubén Toribio primero y con mi sesión de Modern Branding en SharePoint 2013 después y de las que saqué la impresión de que la gente verdaderamente estaba aprovechando el evento.

Finalmente y como siempre acostumbramos allá donde vamos, cerramos el evento con premios, sorpresas con la participación de los últimos valientes que aguantaron hasta el final.

Aquí podéis encontrar las slides de mi sesión sobre Modern Branding en SharePoint 2013

 

Espero que os haya gustado a los que pudisteis asistir y a los que no, el próximo año una nueva oportunidad J

Enjoy coding!

Compilando SASS en Visual Studio con GULP y automatizando tareas

Hasta ahora en Visual Studio disponíamos de una herramienta que nos hacía prácticamente todo el trabajo “engorroso” a la hora de trabajar en el frontend de una aplicación, Web Essentials, pero en la versión para Visual Studio 2015 han anunciado que no incluirían la característica que más uso yo hoy en día de esta herramienta y no es otra que el compilador de SASS
así que, nos va a tocar hacerlo a mano haciendo uso de
Gulp o Grunt
.

No trataré la diferencia entre ambos en este artículo, así que iré directamente al ejemplo que quiero mostrar, compilar SASS con Gulp dentro de Visual Studio 2015.

 

Preparar la solución

Lo primero será instalar las herramientas necesarias en nuestro entorno:

  • Node: Viene integrado con Visual Studio 2015 si lo hemos seleccionado durante la instalación, en caso contrario podéis descargar el instalador desde este enlace
  • Gulp: También viene integrado si lo hemos seleccionado, en caso contrario:
    • npm install gulp -g
    • npm install gulp-sass –g

La opción –g indica que se instale globalmente para poder usar los paquetes desde cualquier lugar.


  • Cread un fichero package.json en la raíz del proyecto y añadid las siguientes líneas.
{
    "name": "Project Name",
    "version": "1.0.0",
    "description": "Project Description",
    "devDependencies": {
        "gulp": "3.8.11",
        "gulp-sass": "1.3.2"
    }
}

 

Si estáis usando la plantilla de Sitio Web de ASP.NET 5 (vNext) ya tendréis ese archivo.

No olvidéis comprobar que la versión de los paquetes Gulp se corresponde con la que tenéis instalada.

 

Creando las tareas Gulp

Una vez tenemos el entorno preparado, ya podemos comenzar a ejecutar tareas de Gulp. Para ello, creamos el fichero gulpfile.js con el siguiente código

var gulp = require('gulp');
var sass = require('gulp-sass');
gulp.task('sass-compiler, function () {
    gulp.src('/css/*.scss')
        .pipe(sass())
        .pipe(gulp.dest('/css/dist'));
});
gulp.task('sass-watcher', function () {
    gulp.watch('./css/*.scss', ['sass-compiler]);
});

 

  • Con esto estamos creando las variables Gulp y Sass necesarias para hacer referencia a las librerías, requeridas.
  • Creamos una tarea Gulp, que llamamos “sass-compiler” en la que especificamos que compile los ficheros sass en la carpeta “css” y que ubique el resultado en la carpeta “css/dist”.
  • Por último, tenemos otra tarea Gulp “sass-watcher” que queremos que esté a la espera de cualquier cambio en ficheros “scss” y que cuando se produzca alguno los compile todos. ¿Por qué todos? Pues porque el que estamos modificando puedes ser por ejemplo un fichero con las variables correspondientes a la paleta de colores del sitio web y el resto de ficheros sea dependiente.

     

Ejecutando las tareas

Llegados a este punto, ya estamos en disposición de poder compilar nuestras hojas de estilo hechas con Sass, así que abrimos el explorador de tareas “Task Runner Explorer” que trae Visual Studio y podremos ver un árbol con nuestro fichero gulpfile.js y las tareas que contiene.

Si ejecutamos la tarea “sass-compiler” (doble click o botón derecho -> Run), podremos comprobar cómo se nos crea una carpeta “dist” dentro de “css” y se despliega el fichero “.css” resultante de la compilación en caso de que haya sido exitosa claro está.

Al ejecutar la tarea “sass-watcher”, se estará a la espera de que haya un cambio en algún fichero y, automáticamente se ejecutará el código que contiene y que hace una llamada a la tarea “sass-compiler”.

 

Automatizando la ejecución de las tareas

Si queremos automatizar el momento del lanzamiento de las tareas, podemos establecer “bindings” con 4 eventos de Visual Studio:

  • Before Build
  • After Build
  • Clean
  • Solution Open

Para ello, con el botón derecho del ratón hacemos click en el nombre de la tarea desde el “Task Runner Explorer” y desplegamos la opción Bindings para seleccionar la que se adapte a nuestras necesidades, como por ejemplo, que se compilen los ficheros Sass antes de la construcción de la solución y que el “watcher” esté activo al abrir la solución. De esta forma, no tendremos que preocuparnos más por lanzar las tareas puesto que será Visual Studio el que se encargue de hacerlo por nosotros cuando ocurran estos eventos.

¿Necesitas más sobre Gulp?

Con Gulp por ejemplo podemos minificar (minimizar) nuestros ficheros Sass, scripts, etc y realizar otras tareas que podrían resultar interesantes que podréis encontrar en su documentación

 

Enjoy coding! :)

 

 

Fantasmas del código | jQuery en SharePoint 2013 en modo edición

Llega una nueva entrega de “Fantasmas del código” y, en esta ocasión le toca a SharePoint 2013 y los problemas con jQuery.

Escenario

Cuando tenemos que personalizar un sitio de SharePoint 2013 es muy probable que hagamos uso de jQuery, plugins, etc… y así dotarlo de “vida” y de nuevas funcionalidades que no vienen por defecto y que queremos añadir en nuestros Web Parts, User Controls, Display Templates, Page Layouts,… y, como todo el mundo sabe, la mejor forma realizar llamadas jQuery es usando el alias “$” como por ejemplo cuando queremos que nuestro código se ejecute cuando la página esté lista.

 

$(document).ready(function() {
// código a ejecutar cuando la página esté lista
});

 

$(function() {
// código a ejecutar cuando la página esté lista

  });

Hasta aquí todo perfecto, nada que no hayamos visto y, lo mejor es que nuestro código funcionará correctamente… o no.

Problema

Ahora comienza la pequeña broma de los becarios
que tocan el código de los productos. Si editamos nuestra página, es bastante probable que todo siga funcionando a las mil maravillas hasta que, de repente, editando una página nos damos cuenta que nuestro código ha dejado de funcionar sin previo aviso, con nocturnidad y alevosía y nos quedamos con cara de Carlo Ancelotti (la ceja hasta el cielo). ¡Pero si esto funcionaba perfecto! O más conocido como “En mi casa funcionaba”. Y aquí podemos tracear y tracear usando el depurador que más nos guste, comprobaremos que el error se debe a que jQuery no está cargado, pero… el fichero aparece en la pila de carga como OK, es decir, ¡que sí que está cargado! ¿Y por qué me dice que no lo está cuando estamos viendo lo contrario?

Solución

La solución es simple y llanamente cambiar “$” por “jQuery” en nuestro código. Como podéis ver es muy simple y a la vez muy engorrosa si hemos avanzado bastante en el desarrollo, además que para los que estamos acostumbrados a usar jQuery va a ser un poco duro adaptarse.

Explicación

Algún becario
(y no quiero señalar…) tuvo la brillante idea de que SharePoint en algunos de sus scripts haga uso de “$” como alias con lo que si SharePoint necesita hacer uso de la funcionalidad que contiene el fichero assetpicker.js o alguno otro más con ese mismo problema, nuestro “$” queridos developers no se referirá a jQuery porque los scripts estarán en modo “battle” y ninguno nos va a responder como debería.

Desde mi punto de vista, que otro script haga uso de “$” como alias es un error de guardería, básicamente por lo extendido que está esta gran librería de JavaScript y que hace muy probable o casi seguro que cualquier desarrollo que incluya JavaScript tendrá una referencia a jQuery, así que mi postura se acerca mucho a la de “Becarios para aprender y no para producir” por favor.

Global Azure Bootcamp | El mayor evento de Azure a nivel mundial

El pasado 25 de abril tuvimos la oportunidad de disfrutar en Madrid del mayor evento de Microsoft Azure a nivel mundial de la mano de los mejores profesionales en España, además de tener un marcado acento canario 😛 . Dado que es una de las tecnologías que más evolucionan día a día, las novedades se encontraban en prácticamente todas las sesiones que se impartieron y, para mejorar aún más el nivel, algunos ponentes montaron su propio “teatro” convirtiendo la sesión en una reunión de estilo medieval. Grande David Nudelman! También pudimos participar en la lucha contra el cáncer, levantando máquinas en nuestras sucripciones donde desplegábamos un proyecto de cálculo de datos y así poder ayudar a recavar información sobre este enemigo del ser humano y poder combatirlo en el futuro. 

Como viene siendo costumbre no falté a mi cita, esta vez acompañando al maese Adrián Díaz (MVP de SharePoint Server) para hablar sobre casos prácticos de Machine Learning y mostrar una demo en la que convertíamos LinkedIn en un buscador de perfiles de usuario mediante el procesamiento de nuestros contactos con Machine Learning y una Web App que, dependiendo de los valores de entrada nos mostraba los perfiles que buscábamos… atentos recruiters que el buscador que necesitabais ha llegado 😛

La guinda de la tarta la pusimos en el sorteo final que contó con la presencia del ya conocido “Preguntón” y que supuso el cierre del evento entre risas y sorpresas ante algunas de las preguntas 😛

Cómo no, el próximo año más y mejor J