Categoría: Trucos

Closures en C#

Para empezar el año y mientras esperamos la llegada de Marty McFly, un minipost sobre closures, una estructura imprescindible en JavaScript y otros lenguajes funcionales, pero ¿las podemos hacer en C#? Y la respuesta es:
¡Por supuesto! Y aquí tenéis un ejemplo:

public static Func<int> Fib()
{
    int a = 0, b = 1;
    return () => { var temp = b; b = a + b; return a=temp; };
}

static void Main(string[] args)
{
    var fib=Fib();

    for (int i = 0; i < 12;i++ )
        Console.Write("{0} ", fib());
}

Como veis el uso de funciones anónimas nos ayuda mucho. El ejemplo lo he sacado de otro lenguaje sobre el que estaba leyendo. Yo ahora me voy a buscar un monopatín 😉

Anuncios

Funcionalidades de Windows 10 en Windows 8

Hace dos días anunciaron Windows 10 y a partir de ayer por la tarde puedes participar en la preview como Insider. Puedes instalarla en una máquina virtual, pero yo ya la he instalado en una partición de mi portátil para conseguir la experiencia al 100%. Ya os iré contando, aunque os advierto que la pantalla de inicio era mi feature favorita de Windows 8 y no se cuanto tardaré en volver a activarla:
Use Start Menu in Windows 10
La cuestión es que hay mucha gente que no va a instalarse Windows 10 en su máquina de uso diario hasta que no sea una versión estable, pero eso no es obstáculo para poder tener algunas cosas que nos traerá Windows 10, aquí tenéis algunas utilidades para mejorar vuestro Windows 8 / 8.1 mientras acaban el nuevo:

  • Cortapega en la consola: en la nueva consola de Windows 10 ya podemos hacer copy/paste con CTRL+C y CTRL+V sin que nos aparezcan los dichosos ^C y ^V, pero hace mucho que existen consolas mejoradas que permiten hacer eso y mucho más. Mi favorita es ConEmu, tiene pestañas, corta/pega y hasta se pueden inyectar plugins.
  • Escritorios múltiples: en Windows 10 por fin tendremos múltiples escritorios. Aunque Windows tenía soporte nativo para esta característica desde hace tiempo, creo que Windows XP ya lo traía, y tenemos una herramienta del conjunto de SysInternals que nos proporciona 4 escritorios. Desktops v2.0, aunque en Windows 8.1 el botón de inicio sólo funciona en la pantalla 1, 😦 grrr.

Pues ahí lo tenéis, mientras tanto yo instalo Visual Studio 14 CTP 3 en Windows 10 a ver qué tal anda…

visual studio 14 in Windows 10

Inhabilitar la transición de entrada para algunos controles del Grid XAML

Las animaciones de entrada, salida, añadir elemento, seleccionar, ordenar, etc., que trae el SDK de la Tienda Windows aportan un toque de calidad a nuestras apps. Las páginas que creamos desde Visual Studio incorporan algunas transiciones por defecto, aunque en algunas ocasiones nos interesará inhabilitarlas.

Eliminar las transiciones de entrada de un Grid es sencillo, sólo tendremos que borrar la colección de transiciones que ya nos habrá añadido el SDK en la página y, por si acaso, asegurarnos que no queda ninguna:

Sigue leyendo

Caché HTTP de cliente en C# (1 de 4): aplicaciones de escritorio

Hoy en día es muy habitual utilizar contenido web en nuestras aplicaciones y eso penaliza el rendimiento. Para mejorarlo vamos a tener que almacenar en caché dicho contenido. Hacerlo bien no es difícil, pero es necesario conocer cómo funcionan los mecanismos de caché en la web y buscar dentro de la documentación de .Net cómo podemos aprovechar estos.

Upload / Download
Upload / Download por johntrainor, en Flickr

Como no soy el primero en tener la necesidad, existen algunas entradas en StackOverflow sobre el tema. Parece que la solución propuesta funciona bien, pero todas los que he visto se olvidan de algunos puntos importantes, como por ejemplo pedir al servidor si hay una versión actualizada del archivo, añadir técnicas de scavenging para que el contenido descargado caduque, etc. Además se olvidan de que el sistema operativo ya sabe cachear y es un poco raro que tengamos que volver a programar el caché que tan bien hacen los navegadores.

Te recomiendo leer el artículo hasta el final, pero si tienes mucha prisa puedes descargar el código de ejemplo en GitHub.

Sigue leyendo

Indice secuencial con Table Storage en Azure

Azure Table Storage es un sistema NoSQL de almacenamiento de tipo clave/valor. Es un sistema pensado para grandes volúmenes de datos distribuidos en alta disponibilidad y algunas cosas que son triviales hoy en día en un motor SQL estándar, en un NoSQL es muy posible que ni siquiera estén contempladas. Esto nos obliga a pensar en otras técnicas o incluso otras formas de almacenar los datos y sus relaciones.
Numbers

Hace unos días necesité un contador secuencial para almacenar en tablas del Table Storage. Ya se que muchos me diréis que no es lo más adecuado para el Storage, pero la secuencia es para mostrar por pantalla y resulta que los humanos llevamos muy mal el retener números de más de seis cifras.
Sigue leyendo

Editar y continuar cuando modificamos el ViewBag en MVC

Hace años que podemos editar y continuar en Visual Studio cuando desarrollamos en ASP.Net con el IISExpress y cada día mejoran esta funcionalidad. En Visual Studio 2013 nos simplificaron la tarea habilitando la opción por defecto:
Edit and continue en Web
Aunque nada es perfecto y hay algunas ocasiones en las que editar y continuar no nos va a funcionar: si es async, si hay un lambda, etc. Uno de esos casos lo encontraremos al modificar el objeto ViewBag, pues es un objeto marcado como dynamic y por ahora no se puede modificar y continuar con este tipo de objetos mientras estamos en ejecución:
Edit and continue with viewbag
En este caso, aunque no nos servirá para todos los escenarios, podemos cambiar el objeto desde la Immediate Window e incluso añadir propiedades si es necesario:
Immediate Window dynamic properties

Deshabilitar el compilador Roslyn temporalmente

El nuevo compilador de .Net todavía está en CTP y no tiene licencia para desplegar aplicaciones en producción. Si instalas Roslyn en la máquina que utilizas para desarrollar cada día, vas a tener que desinstalarlo antes de compilar código para producción, pues sustituye completamente al compilador de .Net, incluso el de línea de comando.

La instalación y desinstalación de Roslyn es bastante rápida, pero tenemos otra forma de deshabilitar el compilador que nos ahorrará algo de tiempo. Será tan fácil como definir el valor true en la variable DisableRoslyn. Podemos indicar este valor de dos formas: como parámetro de msbuild o como variable de entorno.

Desde Visual Studio podemos definir una propiedad a nivel de proyecto que pasará a msbuild y deshabilitará Roslyn, así:

<PropertyGroup>
  <DisableRoslyn>true</DisableRoslyn>
</PropertyGroup>

Pero tendremos que hacerlo a nivel de cada proyecto y si queremos volver a habilitar Roslyn tendremos que volver a editar todos los proyectos. En realidad es mucho más fácil establecer una variable de entorno llamada DisableRoslyn y asignar un true o un false según nos convenga en cada momento:

Disable Roslyn

Yo me he hecho un .bat y lo he añadido a mi barra de tareas como un botón de activar/desactivar:

@echo off
IF "%DisableRoslyn%"=="true" (
setx DisableRoslyn false
echo Roslyn compilation enabled
) ELSE (
setx DisableRoslyn true
echo Roslyn compilation disabled
)
pause 0

Ahora ya no tenéis excusa para probar Roslyn.

Aunque yo me enteré de esto directamente, ahora es más fácil saber estas cosas: basta mirar el código fuente de http://roslyn.codeplex.com, en este caso veréis la explicación en el archivo CompilerPachage.cs:
CompilerPackage.cs
 

Pruebas unitarias, acceso a ficheros y async para Windows 8

Crash Dummy Label
Cuando desarrollas Apps para Windows 8 u 8.1 y usas pruebas unitarias, en algún momento te encuentras con la necesidad de cargar un archivo para realizar una prueba. Parece una tontería, pero si juntas estas tres cosas puedes estar un buen rato hasta que consigues ponerlo todo en marcha.

Las pruebas unitarias de aplicaciones de la tienda Windows se realizan en proyectos especiales que no tienen acceso a toda la librería .Net, sino al subconjunto que tenemos para Windows RT. Que los test se realicen en un entorno limitado como el de producción es lo ideal, pero nos va a dificultar hacer algunas cosas que solemos hacer fácilmente en otros entornos de test, como por ejemplo leer archivos distribuidos con nuestras pruebas.

Empecemos por ejemplo con el siguiente test:

[TestMethod]
public void TestPlainXmlList()
{
    string xml = "<items><item name='one'/><item name='two'/></items>";
    var testable = new TestableClass();
    IEnumerable<string> items = testable.ListItems(xml);
    Assert.IsNotNull(items);
    Assert.AreEqual(2, items.Count());
}

Si ahora queremos realizar la prueba con un archivo que tenemos dentro del test, tendremos que cargarlo y no tenemos acceso a una clase File para cargar el archivo desde el disco. Tendremos que utilizar un StorageFile del API de Windows 8.

Como habitualmente, vamos a añadirlo al proyecto de pruebas y darle un valor “Copy if newer” en las propiedades del fichero:

Unit Test Files Windows 8

Ahora tenemos que abrirlo desde el test para poder enviar el contenido a nuestro método, los archivos que desplegamos con nuestra aplicación están en Windows.ApplicationModel.Package.Current.InstalledLocation. Es un StorageFolder y lo podemos usar como en cualquier App de Windows 8:

[TestMethod]
public async void TestLoadLargeXml()
{
    string largexml;

    var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
    var file = await folder.GetFileAsync("Files\\test1.xml");
    using (var fileopen = await file.OpenReadAsync())
    {
        using (var stream = fileopen.AsStreamForRead())
        {
            using (var r = new StreamReader(stream))
            {
                largexml = r.ReadToEnd();
            }
        }
    }

    var testable = new TestableClass();
    IEnumerable<string> items = testable.ListItems(largexml);
    Assert.IsNotNull(items);
    Assert.AreEqual(60, items.Count());
}

Como en Windows 8 tenemos muchos métodos asíncronos, hemos tenido que utilizar las palabras async/await pues las operaciones con archivos son asíncronas, pero tal como está escrito el método de test vamos a encontrarnos un problema: no aparecerá el método en el listado de pruebas y no tendremos manera de probarlo.

Los métodos async void no se pueden probar directamente

Esto es así porque un método declarado async void no es awaitable, simplemente se ejecuta en un hilo aparte en modo “fire and forget”, así que el framework de test no podrá saber cuándo ha acabado y lo ignora.
Para que sea awaitable bastará con que el valor de retorno sea una Task en lugar de void, tal que así:

[TestMethod]
public async Task TestLoadLargeXml()

A partir de este momento podremos ejecutar las pruebas sobre nuestros métodos de Windows 8/8.1.
Ahora sólo falta que algún día las pruebas funcionen bien en el VSOnline para tener todo lo que necesitamos para probar nuestras Apps.

Feliz testing!

¿Como esperar con await en una expresión lambda?

Hoy he necesitado escribir un código dentro de una lambda que llamaba a métodos asíncronos. Normalmente estamos acostumbrados a marcar métodos asíncronos con la palabra async y ya podemos usar await a diestro y siniestro, pero ¿cómo se hace con una lambda? Pues en realidad igual, marcando la lambda con async:

Task.Factory.StartNew(async () =>
{
    await Task.Delay(1000);
});

Y por supuesto, la función lambda también es awaitable:

Func<Task<string>> t = async () =>
{
    await Task.Delay(1000);
    return "Hello";
};
System.Diagnostics.Debug.WriteLine(await t());

Por cierto, id con cuidado con ésto último que he hecho, poner un await como argumento, pues puede que nos llevemos alguna sorpresa… pero ya os lo cuento en otro mini-post.

Consumir SOAP desde WinJS

soap
No todos los servicios proporcionan una API Restful para acceder a ella de forma sencilla desde nuestras Apps, así que es posible que tengamos que pelearnos con servicios SOAP, que son más pesados y complicados, pero a la vez nos permiten trabajar operaciones y conjuntos de datos más complejos.
Consumir SOAP desde JavaScript no es complicado, sólo que es tedioso. Hoy vamos a ver dos maneras que podremos utilizar en nuestras aplicaciones de la tienda Windows.

Descarga el código de ejemplo de Codeplex

Consumir SOAP con xhr

WinJS.xhr es un wrapper del objeto XMLHttpRequest para facilitarnos las llamadas asíncronas, así que utilizar SOAP desde xhr va a ser tan sencillo o complicado como con el XMLHttpRequest original.

Para el siguiente código vamos a utilizar uno de los ejemplos de servicios web SOAP que hay en http://www.webservicex.net/, en concreto el servicio ChangeLengthUnit que realiza conversión de unidades.

En una aplicación de la tienda Windows creamos una página y en el tag body ponemos un cuadro de texto, un botón y un div como estos:

Introduce los centímetros: <input type="number" id="mmValue" value="0.0"/>
<button id="xhrTest">Conexión con WinJS.xhr</button>
<div id="result"></div>

En default.js, añadimos el código que sigue tras la línea donde se llama a WinJS.UI.ProcessAll(), creando el código XML que enviaremos al servicio SOAP para llamar a la acción SOAP ChangeLengthUnit. Podéis ver un ejemplo en la página de descripción de la operación, necesita tres parámetros: el valor numérico, las unidades origen y las unidades destino. Para el ejemplo convertiremos de centímetros a pulgadas:

var data = '<?xml version="1.0" encoding="utf-8"?>' +
            '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ' + 
            ' xmlns:xsd="http://www.w3.org/2001/XMLSchema" ' +
            ' xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">' +
            '  <soap:Body>' +
            '    <ChangeLengthUnit xmlns="http://www.webserviceX.NET/">' +
            '      <LengthValue>'+mmValue.value+'</LengthValue>' +
            '      <fromLengthUnit>Centimeters</fromLengthUnit>' +
            '      <toLengthUnit>Inches</toLengthUnit>' +
            '    </ChangeLengthUnit>' +
            '  </soap:Body>' +
            '</soap:Envelope>';

var options = {
    url: "http://www.webservicex.net/length.asmx",
    type: "post",
    headers: {
        "Content-Type": "text/xml; charset=utf-8",
        "SOAPAction": "http://www.webserviceX.NET/ChangeLengthUnit"
    },
    data: data
};

Fijaos que he configurado la llamada xhr para llamar por POST y he incluido dos cabeceras específicas para la llamada, el Content-Type, que debe ser xml y la SOAPAction, que debe indicar a qué servicio estamos llamando. Ahora llamamos a la función xhr con las opciones que hemos configurado y esperamos la respuesta, que vuelve a ser un XML del que podremos extraer la información.

WinJS.xhr(options)
.done(
    function (request) {
        var doc = request.responseXML.documentElement;
        var output = doc.getElementsByTagName("ChangeLengthUnitResult");

        result.innerHTML = "La longitud es "+ window.toStaticHTML(output[0].textContent)+" pulgadas";
        result.style.backgroundColor = "#00A000";
    },
    function (error) {
        result.innerHTML = "Status: " + error.status + " : " + error.statusText;
        result.style.backgroundColor = "#FF0000";
    },
    function (progress) {
        result.innerText = "Ready state is " + progress.readyState;
        result.style.backgroundColor = "#0000A0";
    });

Todo esto para un servicio web bastante sencillo. Si empezamos a añadir tipos de datos complejos la cosa se complica.
Como estamos en Windows 8 / 8.1, tenemos una gran ventaja, podemos realizar la conexión con el servicio web mediante C#, que es capaz de leer la descripción WSDL del servicio y generar un proxy con las clases tipificadas, para luego utilizar esa clase desde JavaScript a través de las proyecciones WinMD.

Puente SOAP con C#

Como ya comenté en un artículo anterior, podemos utilizar librerías escritas en C# o C++ desde nuestros proyectos JavaScript, sólo tenemos que crear una librería tipo Windows Runtime Component y respetar unas normas básicas. Una vez creada la librería y referenciada desde nuestro proyecto JavaScript, utilizar servicios SOAP es muy fácil, basta con pulsar botón derecho sobre el proyecto C# y añadir una referencia al servicio. El Visual Studio nos creará las clases y llamadas que necesitamos para comunicarnos con el mismo.

Add WebService

Con la referencia al servicio ya tenemos todo lo necesario, sólo nos falta crear un método dentro de una clase C# para publicarlo y que se pueda utilizar desde JavaScript. Como las llamadas al servicio son asíncronas creamos un método que devuelve un tipo IAsyncOperation; podemos convertir la Task del cliente SOAP directamente a este interfaz con el método de extension AsAsyncOperation:

public sealed class LengthUnits
{
    LengthUnitService.lengthUnitSoapClient client;
    public LengthUnits()
    {
        client = new LengthUnitService.lengthUnitSoapClient();
    }
    public IAsyncOperation<double> GetAsync(double number,
        LengthUnitService.Lengths from, LengthUnitService.Lengths to)
    {
        return client.ChangeLengthUnitAsync(number, from, to).AsAsyncOperation();
    }
}

Et voilà, ya lo podemos utilizar desde JavaScript sin ensuciarnos las manos parseando XML:

csTest.onclick = function (e) {
    var cl = new SoapClient.LengthUnits();
    cl.getAsync(mmValue.value, SoapClient.LengthUnitService.Lengths.millimeters, SoapClient.LengthUnitService.Lengths.inches).done(
        function (c) {
            result.innerHTML = "La longitud es " + c + " pulgadas";
            result.style.backgroundColor = "#00a000";
        },
        function (err) {
            result.innerHTML = window.toStaticHTML(err);
            result.style.backgroundColor = "#FF0000";
        },
        function (progress) {
            result.innerHTML = window.toStaticHTML("percent: " + progress + "%");
            result.style.backgroundColor = "#0000a0";
        }
        )
}

Progreso

Un momento, ¿ahora no está llegando nunca a la función de progreso? Pues no, porque para tener progreso necesitamos utilizar el interfaz IAsyncOperationWithProgress. Nos llevará un poco más de trabajo, la clase AsyncInfo y las palabras async y await nos lo van a poner fácil:

    public Windows.Foundation.IAsyncOperationWithProgress<double, string> GetWithProgressAsync(double number,
        ServiceReference1.Lengths from, ServiceReference1.Lengths to)
    {
        return AsyncInfo.Run(async delegate(CancellationToken cancellationToken,
            IProgress<string> progress)
        {
            double result;
            progress.Report(client.State.ToString());
            await client.OpenAsync();
            progress.Report(client.State.ToString());
            result = await client.ChangeLengthUnitAsync(number, from, to);
            progress.Report(client.State.ToString());
            await client.CloseAsync();
            progress.Report(client.State.ToString());
            return result;
        });
    }

Seguro que hay alguna manera más, cuando la encuentre os la contaré!

Descarga el código de ejemplo de Codeplex