Primeros pasos con ASP.net vNext

Desde hace pocas horas podemos acceder al código de las primeras demos de ASP.net vNext. En este artículo veremos cómo configurar nuestro entorno para usar kvm y además veremos qué trae el código de pruebas.

KVM y KRE

Uno de los grandes cambios a partir de esta versión es que ya no hablamos de un único .NET framework, sino de múltiples versiones que existen de manera concurrente (como ocurre con los paquetes de nuget) y para la gestión de estas versiones tenemos el K Version manager que gestionará la K Runtime Environment, que es lo primero que debemos obtener.

Para su instalación necesitamos clonar el repositorio que aloja la solución en github:

git clone https://github.com/aspnet/home.git

Una vez descargado, el siguiente paso es ejecutar kvmsetup.cmd para agregar kvm a nuestro path. Para finalizar esta fase, necesitamos obtener la versión del KRE con la que vamos a trabajar, en este caso la 0.1 alpha.

kvm install 0.1-alpha-build-0421

Al finalizar contaremos con los siguientes ficheros:

Capture_alpha

Descargando el código de ejemplo

Ya con todo listo para empezar a “cacharrear” podemos obtener el código del bugtracker:

git clone https://github.com/aspnet/BugTracker.git

Y justo a continuación movernos a la rama “dev”, que es la más actualizada.

git checkout dev
git pull origin dev

Una vez descargado, el siguiente paso es ejecutar el comando kpm restore desde la carpeta \src\BugTracker para que configure nuestro entorno. Este comando descargará los componentes de .NET y las librerías de terceros que necesite nuestra aplicación:

Capture_restore

Estos requisitos vienen definidos en un nuevo fichero, llamado project.json, que incluye por una parte dependencias, acciones permitidas, y configuraciones soportadas. Hasta ahora esta información solamente la encontrábamos o bien en el proyecto, o en fichero packages.config de nuget, pero ahora se unifican.

Una vez que el proceso de “restore” finalice, tenemos varias opciones para arrancar la solución, en mi caso he optado por arrancar un IIS Express mediante el comando Helios.cmd, y he aquí el resultado:

Capture_hosting

Cosas que han cambiado

Además de la gestión de dependencias, tenemos más novedades, si echamos un vistazo a la carpeta src, como que no encontramos fichero Global.asax, y que el fichero Startup.cs contiene toda la información de inicialización (que estamos acostumbrados si hemos trabajado con SignalR o Web API).

Tanto si ejecutamos la app como aplicación web como aplicación de consola usando el código de Program.cs, ambos buscarán la configuración en el fichero Startup.cs, el primero por convención y el segundo por la línea services.GetService()

Otro gran cambio, que empezó con SignalR y Web API, es que la dependencia de System.Web desaparece por completo, siendo sustituida para MVC por Microsoft.AspNet.Mvc

Conclusiones

Puede que sacar conclusiones para un primer vistazo sea algo precipitado, aunque resulta interesante el concepto y cómo se ha planteado la manera de modularizar el .net framework, y vemos cómo van tomando forma y convergiendo iniciativas como owin, katana, web api, signalR o el propio NuGet. Queda mucho por llegar…

Más información:

Primer contacto con Redis desde C#

Tenemos muchos tipos de bases de datos en memoria, como MongoDB o RavenDB, aunque hay una de ellas que se emplea especialmente para labores de caché, y esa es Redis. En este artículo veremos algunas nociones de Redis así como su uso desde C#.

Sobre Redis

Redis no es, ni mucho menos, el último en llegar, de hecho se usa en portales como Pinterest, Twitter, Github y Stack Overflow. La base de datos se mantiene en memoria, con lo cual el acceso clave-valor para lectura y escritura son increiblemente rápidos.

Como en mi caso lo que necesitaba era una caché (de hecho no necesitaba ni siquiera que expirara) solamente necesitaba dos comandos: get y set. Las claves a usar son cadenas de texto (string), y los valores puede ser de tipo texto (string), listas o conjuntos de manera nativa.

La manera más sencilla de empezar a trabajar con Redis en Windows es a través de Chocolatey, una vez instalado solamente necesitamos.

cinst redis

Redis desde C#

Existe multitud de librerías que podemos usar para ello, siendo la más distribuida la de ServiceStack, que nos permite procesar un número máximo de 4000 peticiones por hora, ya que tiene soporte comercial.

Para agregar Redis a nuestra solución, lo más sencillo es a través de NuGet (disponemos además de una versión firmada por si nuestro proyecto lo requiere):

Install-Package ServiceStack.Redis

También podemos descargar la solución desde el repositorio de Github y construirla por nosotros mismos. Una vez instalada, si estamos trabajando desde el mismo ordenador donde hemos instalado redis, se conectará por defecto a localhost:6379, y podremos acceder mediante el siguiente código:

using ServiceStack.Redis;
public class MyRedisHelper
{
  private RedisClient redisClient;
  public MyRedisHelper()
  {
    //Por defecto, a localhost:6379
    this.redisClient = new RedisClient();
  }

  public void Set(string key, string value)
  {
    //Tanto el metodo get como set son genericos
    this.redisClient.Set<string>(key, value);
  }

  public string Get(string key)
  {
    this.redisClient.Get<string>(key);
  }
}

Solamente con estas líneas de código, ya tenemos acceso a nuestra instalación de redis y podemos hacer uso de nuestra caché. En el caso de Set, podemos, como parámetro adicional, especificar una fecha de expiración o un tiempo máximo, por si necesitamos que los datos de nuestra caché sean volátiles.

Más información:

My february pet project: RealPoll (10+ technologies + a lot of fun)

Test it live: Realpoll at Azure

After my fist side-project (which I might publish on march or april) with Angular.js, I’ve been playing with different web technologies by doing a remake of a hackathon idea: Meet realpoll.

welcomeToRealPoll

The Idea

Teachers and speakers often need a way to engage the audience and give them the possibility to participate in the talk or the subject. Today is very common to see students tweeting from class, so this means they do have portable, wireless internet. The response of some centers is to block communications, but, why not use it the other way?

This web app allows the teachers to previously prepare some questions, choose the number of answers, the correct ones, and display the question on a projector. The students can then, use the url or capture the QR code generated from their cell phones. Once the question is generated, the trainer can choose the time that will be the poll open (in seconds).

When the time is up, the dashboard will mark the correct answers and those who answered correctly. The only data that is saved is the question and the answers, so you can come back and repeat it.

The voting interface is very, very simple: Just add a name and click on your chosen answer. It will be send inmediately to the dashboard.

Remake of a classic

The fact is that realpoll is a previous project done in a hackathon using a completely different tooling:

  • 100% HTML + Javascript
  • redis for the data layer
  • socket.io for handling the real time interaction
  • express.js for handling routing and views
  • google charts for the graphics
  • plain jquery for DOM management
  • Heroku as cloud host
  • developed with VIM

For this project, I wanted to keep the idea, but change completely the technologies used:

  • 50% HTML + Javascript, 50% C#
  • sql + entity framework for the data layer
  • signalr for the real-time interaction
  • ASP.net MVC for handling routing and views
  • Chart.js for the graphics
  • jquery and Angular.js for handling the views
  • RazorEngine for the views
  • Git/github as SCM
  • Windows Azure as cloud host (connected to github)
  • Visual Studio + IE dev tools + Chrome dev tools (+ Safari dev tools on mac)
  • Sendgrid for mailing.

Items

Architecture

The backend is pure ASP.net MVC with the data stored in a SQL Server database, and some services (such as email) for making my life a little bit easier.

The system uses the database for storing the questions, so we can access later from a single URL. The URL is a hash based on the question ID. The voting process is not stored, so it resets when we refresh the dashboard. The communication between the database and the app is done by using Entity Framework, Microsoft’s open source ORM.

For being able to use data without having to worry about the ORM, I used dependency injection techniques to inject a fake data source. The Depencency Injection framework chosen was ninject, and while I had to create two different classes for ASP.net MVC and SignalR dependency solvers, I had a single entry point to replace the fake access with the ORM data source.

Flow

Architecture

New question

The “New” page looks like this, It’s bootstrap for the UI and angular for handling the UI updates when the question number changes:

CreateQuestion

Created

When we create a question, data is updated in the database and we see a confirmation page like this:

Created

For generating the e-mail sent I use RazorParser, a nuget-available dll that allows me to generate an html view from a model and a file, and once generated use it as a string. The e-mail is sent through sendgrid’s SMTP, using the standard SMTP functions.

Result/dashboard Page

The result page is one of the most complicated, the charts are created by using chart.js with a wrapper for angular, the qr code is generated by using the qrickit API, and it’s updated in real time by using signalR and angular.js for handling the views.

Dashboard

When the time is up, the correct solution is highlighted, and those whose answer matches are highlighted also

Mobile Interface

Mobile

As Bootstrap is mobile ready, I had to do few changes to make the ui work flawlessly, had to do some debugging on Safari for Mac (whose web developer tools are way less powerul than Chrome/IE’s) connected to an iPhone. The cookie consent also adapts so, no issues here.

Stats and cookies

As the goal of the project was to play with technology, I havne’t been playing troo much with stats, but I did have added a google analytics code in each page. Also as I’m on the EU, there is a strict control of which cookies can be installed in the user’s machine (even more strict in Spain) so I’ve used the cookie consent code that allows the user to control the analytics tracking.

Source control, deploy and debug.

The project has been done by using git as source control manager, github as repository and the deployment has been done in Windows Azure. Azure has a hook for git, so when I push to github it will deploy to azure. As is git-based, it allows me to rollback inmediately while keeping the continuous deployment options available.

Finally, for remote debugging I added Elmah (Error Logging Modules and Handlers) to track down exceptions and issues that happened in Azure.

Issues, curious and weird things

  • There is a bug with angular an Visual Studio’s browser link that causes constant debugger stops on frontend code, be aware.
  • For adding dependency injection with ninject for signalR and MVC, you need to define two different dependency solvers, because they belong to different assemblies and implement different interfaces.
  • Validating input data has become way easier with HTML5, butS afari (and specially safari for iPhone) do not support the required tag for html, a useful guide is caniuse
  • For debugging on Safari for iPhone you need Safari running on Mac OS X.
  • When you re-deploy a solution to azure, (with the configuration by default) you lose all the exceptions tracked by elmah
  • I’ve used some funny xml transformations for handling local, remote and fake databases.

Room for improvement

Of course, there are always things that may go better, I didn’t write a single line of test code (other than my fake db wrapper) so it should be considered fairly unstable. The goal of this mini-project was to integrate as many technologies as possible to create a ready-to-deploy real-time web application. I would have added some UI tests with selenium, and maybe some unit testing for both angular and mvc controller.

Try it!

You can test it live on Realpoll at Azure or you can get the source code from the project’s github repository and deploy it by yourself. You will need your own API keys and your own database for making it work. Comments will also be apreciated, and if you want to contribute back, just send a pull request!

Transformando web.config (o app.config) para depuración

Una de las características más interesantes de los ficheros web.config, es que al publicarlos podemos aplicar una serie de transformaciones a los mismos, de tal manera que ciertos datos que estén en depuración no lleguen en modo release, y viceversa.

Sin embargo, hay casos en los que nos puede ser útil tener varios ficheros config para las diferentes configuraciones de build. En mi caso, desarrollando RealPoll, me di cuenta que esto podría ser interesante, y he creado tres configuraciones:

  • Debug_FakeDB
  • Debug_LocalDB
  • Debug_RemoteDB

Para cada una de las opciones tengo un fichero web.config diferente. El problema es que la transformación solamente se aplica al publicar, y no en el proceso de depuración, por lo tanto son poco útiles estos perfiles. Sin embargo, buscando un poco en internet encontré este artículo en CodeProject en cuyos comentarios estaba la respuesta a mi problema, modificar (a mano) el fichero csproj y agregar la siguiente directiva tras la compilación (tenemos un ejemplo comentado al final de nuestro proyecto):

<Target Name="AfterBuild">
   <TransformXml Source="Web.Base.config" Transform="Web.$(Configuration).config" Destination="Web.config" StackTrace="true" />
 </Target>

Una vez agregada, deberemos entonces duplicar la información de nuestro web.config (o app.config si desarrollamos una aplicación de escritorio) en un fichero llamado web.base.config (por ejemplo), ya que tras cada compilación el fichero web.config se regenerará.

Dentro de cada fichero de configuración, tenemos diferentes opciones. En el caso de debug_fakedb se agrega una clave a appsettings, que luego consulto al inicializar mi código:

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <appSettings>
    <add xdt:Transform="Insert" key="FakeDB" value="true" />
  </appSettings>
</configuration>

Esta clave luego la consulto a la hora de inicializar el código:

if (string.IsNullOrEmpty(ConfigurationManager.AppSettings["FakeDB"]) == false)
    Current.Bind<IQuestionRepository>().To<FakeQuestionRepository>();

else
    Current.Bind<IQuestionRepository>().To<DBQuestionRepository>();

Lo bueno de dejar estos valores en claves de configuración es que nos permite hacer cambios “en caliente” sin tener que recompilar la aplicación, como bien recomendaban Andy Hunt y Dave Thomas en su “Pragmatic Programmer”.

En el caso de localDB agregamos la información de Entity Framework (que ya sabrá que hacer):

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <entityFramework xdt:Transform="Insert">
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
</configuration>

Finalmente, para el caso de remoteDB, agregamos la información de Entity Framework, así como la cadena de conexión (que más adelante se sustituye en azure):

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings xdt:Transform="Insert">
      <add name="QuestionContext"
           connectionString="YOUR_CONNECTION_STRING_HERE"
           providerName="System.Data.SqlClient" />
  </connectionStrings>
  <entityFramework xdt:Transform="Insert">
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework"/>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

Para mí supone un ahorro considerable de tiempo y esfuerzo, además de que me permite probar las diferentes configuraciones sin recompilar.

Si quieres verlo en ejecución, echa un vistazo al código de Realpoll en github del que hablaré muy, muy pronto.

Depurando un crash de explorer.exe en Windows 8.1

Hace unos días mi explorador de Windows 8.1 empezó a fallar, teniendo cuelgues cada cierto tiempo que me llegaban a bloquear una buena parte del sistema, y que concluían con un reinicio automático del explorador. Lo curioso es que no era posible reproducirlo, así que, para intentar averiguar qué pasaba, me he armado de valor y me he propuesto depurarlo.

En este artículo veremos los diferentes pasos que he ido dando.

1. Generar un dump:

Para poder depurar primero tenemos, o bien que adjuntar un depurador a la aplicación y esperar a que falle, o bien generar un volcado de la memoria (dump) en el momento del fallo. Como explorer no lo realiza de manera automática, hemos de agregar al registro de windows la siguiente clave:

https://onedrive.live.com/?cid=128FC518635BE2DC&id=128FC518635BE2DC%21346

De esta manera, cuando ocurra el crash, no podremos evitarlo (en principio) pero sabremos donde mirar.

Cuando terminemos de recopilar logs, podemos restaurar el estado anterios, empleando una clave de registro similar:

https://onedrive.live.com/?cid=128FC518635BE2DC&id=128FC518635BE2DC%21672

2. Instalar el SDK de Windows:

El SDK de Windows (8.1 en mi caso) incluye los depuradores para 32 y 64 bits, y se instala por defecto en C:\Program Files (x86)\Windows Kits\Debuggers\x64 El depurador que usaremos es WinDbg.

Para descargar el sdk deberemos ir a http://msdn.microsoft.com/en-us/windows/hardware/hh852365

3. Cargamos el dump anteriormente generado

Si hemos tenido suerte y desde que lo instalamos hemos sufrido algún crash, podemos entonces analizarlo. Para ello vamos a la ruta anterior, ejecutamos WinDbg, vamos a “File > “Open Crash Dump” y seleccionamos nuestro fichero de dump (Que estará situado en la carpeta

explorer crash

4. Inicializar los servidores de símbolos

Abrimos “Symbol File Path…”

SRV*C:\WebSymbols*http://msdl.microsoft.com/download/symbols

Recargamos la lista de símbolos de nuestro dump usando el siguiente comando.

.reload

5. Iniciar análisis

Una vez que la lista de símbolos está cargada, solamente nos queda iniciar el análisis

!analyze -v

Una vez terminado el análisis (que va a tardar bastante) tendremos un resultado como este:


*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

*** ERROR: Symbol file could not be found.  Defaulted to export symbols for sppc.dll - 

FAULTING_IP: 
comsvcs!CNewMonikerClassObject::ParseDisplayName+0
00007ff8`5ba62cf4 ??              ???

EXCEPTION_RECORD:  ffffffffffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 00007ff878c01759 (ntdll!RtlVirtualUnwind+0x0000000000000091)
   ExceptionCode: c0000006 (In-page I/O error)
  ExceptionFlags: 00000000
NumberParameters: 3
   Parameter[0]: 0000000000000000
   Parameter[1]: 00007ff85ba62cf4
   Parameter[2]: 00000000c0000185
Inpage operation failed at 00007ff85ba62cf4, due to I/O error 00000000c0000185

CONTEXT:  0000000000000000 -- (.cxr 0x0;r)
rax=000000001282de78 rbx=00000000127b1570 rcx=0000000000000001
rdx=00007ff85b960000 rsi=0000000000000000 rdi=00007ff85ba62cf4
rip=00007ff878c01759 rsp=00000000127b1410 rbp=00007ff85ba91b5c
 r8=00007ff85ba62cf4  r9=00007ff85babab2c r10=0000000000000b99
r11=00007ff85b960000 r12=0000000000000000 r13=00000000127b14e8
r14=00007ff85babab2c r15=0000000000000001
iopl=0         nv up ei ng nz ac po cy
cs=0033  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010297
ntdll!RtlVirtualUnwind+0x91:
00007ff8`78c01759 803f48          cmp     byte ptr [rdi],48h ds:00007ff8`5ba62cf4=??

DEFAULT_BUCKET_ID:  WRONG_SYMBOLS

PROCESS_NAME:  explorer.exe

ERROR_CODE: (NTSTATUS) 0xc0000006 - The instruction at 0x%p referenced memory at 0x%p. The required data was not placed into memory because of an I/O error status of 0x%x.

EXCEPTION_CODE: (NTSTATUS) 0xc0000006 - The instruction at 0x%p referenced memory at 0x%p. The required data was not placed into memory because of an I/O error status of 0x%x.

EXCEPTION_PARAMETER1:  0000000000000000

EXCEPTION_PARAMETER2:  00007ff85ba62cf4

EXCEPTION_PARAMETER3:  00000000c0000185

IO_ERROR: (NTSTATUS) 0xc0000185 - The I/O device reported an I/O error.

EXCEPTION_STR:  0xc0000006_c0000185

ADDITIONAL_DEBUG_TEXT:  Followup set based on attribute [Is_ChosenCrashFollowupThread] from Frame:[0] on thread:[PSEUDO_THREAD]

LAST_CONTROL_TRANSFER:  from 0000000000000000 to 0000000000000000

NTGLOBALFLAG:  0

APPLICATION_VERIFIER_FLAGS:  0

APP:  explorer.exe

ANALYSIS_VERSION: 6.3.9600.16384 (debuggers(dbg).130821-1623) amd64fre

MANAGED_STACK: !dumpstack -EE
OS Thread Id: 0x3eb4 (22)
Current frame: 
Child-SP         RetAddr          Caller, Callee

PRIMARY_PROBLEM_CLASS:  WRONG_SYMBOLS

BUGCHECK_STR:  APPLICATION_FAULT_WRONG_SYMBOLS

STACK_TEXT:  
00000000`00000000 00000000`00000000 hardware_disk!Unknown+0x0


STACK_COMMAND:  .ecxr ; kb ; ** Pseudo Context ** ; kb

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  hardware_disk!Unknown

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: hardware_disk

DEBUG_FLR_IMAGE_TIMESTAMP:  0

FAILURE_BUCKET_ID:  WRONG_SYMBOLS_c0000006_hardware_disk!Unknown

BUCKET_ID:  APPLICATION_FAULT_WRONG_SYMBOLS_hardware_disk!Unknown

IMAGE_NAME:  hardware_disk

ANALYSIS_SOURCE:  UM

FAILURE_ID_HASH_STRING:  um:wrong_symbols_c0000006_hardware_disk!unknown

FAILURE_ID_HASH:  {95c4d6f5-b6a7-b83a-dfd6-d872fc207cf6}

Followup: MachineOwner
---------

Tras echar un vistazo al crash, y consultar por los rincones de Internet, parece ser que la clave está aquí: IO_ERROR: (NTSTATUS) 0xc0000185 – The I/O device reported an I/O error. Es decir, tengo algún tipo de error de disco. Tocará seguir investigando con otras herramientas. Aunque no he podido conseguir mi objetivo final (reducir o eliminar los fallos) usando windbg, he podido hacer un pequeño diagnóstico gracias a windbg.

Dejo abierta al lector la siguiente pregunta, qué tipo de problemas has podido resolver usando windbg o similar?

Sigue la conversación en Reddit

Clases abstractas VS Interfaces + métodos de extensión en C#

El uso de clases abstractas y herencia para organizar la lógica de nuestras aplicaciones se puede sustituir o complementar con interfaces y métodos de extensión usando C#. En este artículo veremos un ejemplo de ambas aproximaciones así como sus ventajas e inconvenientes.

Clases Abstractas

Las clases abstractas nos permiten tener una clase base con cierta funcionalidad común ya implementada, sobre la que podemos heredar y especificar algunos métodos. Para este ejemplo, la clase Transporte implementa el método Mover, y las clases Coche y Bicicleta especifican el número de ruedas.

public abstract class Transporte
{
    public sealed void Mover()
    {
        Console.WriteLine("Moviendo {0} ruedas", Ruedas);
    }

    public abstract int Ruedas { get; }
}

public class Coche : Transporte
{
    public override int Ruedas
    {
        get { return 4; }
    }
}

public class Bicicleta : Transporte
{
    public override int Ruedas
    {
        get { return 2; }
    }
}

En el caso de que el método no pudiera ser reimplementado por clases hijas, debemos usar el indicador sealed como se muestra. De esta manera las clases hijas no podrán sobreescribir esta funcionalidad. Lo que tenemos aquí es un sistema “ES-UN”, es decir, una bicicleta es un transporte, y un coche es un transporte. Esta relación se basa en la herencia, y solo se permite heredar de una única clase en C#.

El hecho de poder heredar de solamente una clase nos puede generar acoplamiento y la necesidad de otro tipo de alternativas cuando la única opción que tenemos es heredar de una clase específica.

Una alternativa al uso de clases abstractas viene dado por las interfaces y los métodos de extensión:

Interfaces

A diferencia de las clases abstractas, una interfaz por sí sola no aporta funcionalidad, sino que fija un contrato que pueden implementar de manera distinta otras clases.

Por otra parte, un método de extensión nos permite agregar funcionalidad a una clase, y es en lo que se basan componentes como Linq. Si combinamos ambas características, podemos obtener un comportamiento similar como se muestra a continuación:

static class ITRansporteExtensions
{
    public static void Mover(this ITransporte transporte)
    {
        Console.WriteLine("Moviendo {0} ruedas", transporte.Ruedas);
    }
}

public interface ITransporte
{
    public abstract int Ruedas { get; }
}

public class Coche : ITransporte
{
    public override int Ruedas
    {
        get { return 4; }
    }
}

public class Bicicleta : ITransporte
{
    public override int Ruedas
    {
        get { return 2; }
    }
}

Cuando combinamos una interfaz con un método de extensión, dotamos de métodos a clases e interfaces que originalmente no tenían. Como ventaja adicional está el hecho de que podemos implementar varias interfaces al mismo tiempo, con lo cual podríamos acceder a los métodos de extensión de todos ellos.

La desventaja de usar métodos de extensión es que como no estamos accediendo a los campos internos de la clase, solamente vamos a tener acceso a la interfaz que se defina para nosotros.

Conclusiones

Ambas características nos permiten llegar a un resultado común, si bien el uso de clases abstractas nos permite un diagrama de herencia mas claro, en ocasiones podemos optar a una alternativa más abierta. Los métodos extensores no son mas que, como dicen los anglosajones “syntactic sugar”, es decir, una manera mas cómoda de llamara a un método estático que procesa una interfaz.

¿Y tu, usas clases abstractas o interfaces?

Actualización: Gracias a Sergio por el comentario, en efecto, el indicador sealed nos dice que el método no puede ser reimplementado o sobresscrito.
Actualización 2: Gracias Anti por un par de correcciones de estilo!

SignalR with external assemblies and obfuscators

Developing with SignalR is a very interesting experience. The technology, which allows us to create solutions that interact in real time with the browser and native apps, provides us with several layers of abstraction over technologies such as WebSockets, so that we can focus on the specific features of our apps. However, sometimes these abstractions may be a problem more than a solution.

One of the cases we can see this is with the hubs. A hub is a class that, when processed by signalR, is exposed to the browser by using Javascript. Unlike a REST API, a hub does not (only) responds to a request, they can also send messages both to the client who has made the request, the rest of the clients connected, or all of them, in real time.

To define a hub, we only need a class that inherits from the Hub class and SignalR will do the rest. It will discover (by using reflection) all the different hubs in the current assembly and generate the corresponding javascript.

Here is an example with the following code in C#:

public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }
    }

The generated code by SignalR looks a little bit like this:

 proxies.chatHub = this.createHubProxy('chatHub');
        proxies.chatHub.client = { };
        proxies.chatHub.server = {
            send: function (name, message) {
                return proxies.chatHub.invoke.apply(proxies.chatHub, $.merge(["Send"], $.makeArray(arguments)));
             }
        };

As I mentioned earlier, signalR hubs are discovered automatically for the current assembly. What hapens if we store our hubs on a different asembly, for example, if we have two apps who use the same hub? After searching, I found the solution on StackOverflow. As I only needed to load one specific assembly, I picked only this line:

AppDomain.CurrentDomain.Load(typeof(Namespace.ChatHub).Assembly.FullName);

This code loads the Assembly that contains the class so SignalR can “discover” the Hub, we must place it just before the app.MapSignalR() or otherwise the Hub will not be generated.

Obfuscation

If we distribute our application our clients (for example when offering a solution containing SignalR so that they can install it on a local server) is usual to use tools like SmartAssembly or Dotfuscator, to protect the intellectual property of your code.

For a correct SignalR operation, it’s important to remember that we must not obfuscate, or prune the Hub classes, since the class is loaded by reflection. The obfuscation result will rename the classes and probably remove uncalled code (that is, in fact, called from Javascript). The best solution is to use hubs as a ‘proxy’ class and obfuscate those classes and methods called from the hub.

To avoid obfuscation you can can, either manually in the properties of the project, or through attributes. For SmartAssembly we find attributes such as [DoNotObfuscateType] and [DoNotPruneType] which apply to the whole class, and in the case of Dotfuscator we can use the [Obsufcation] attribute.

More information

Un tip rápido: SignalR, ensamblados externos y ofuscación

Desarrollar con SignalR es una experiencia muy interesante. La tecnología, que nos permite crear soluciones que interactúen en tiempo real con el navegador y con aplicaciones nativas, nos proporciona varias capas de abstracción sobre tecnologías como WebSockets, para que podamos centrarnos en el contenido de nuestras aplicaciones. Sin embargo, a veces los árboles no dejan ver el bosque.

Uno de los ejemplos se nos da con los hubs. Un hub es una clase que signalR expone al navegador mediante Javascript. A diferencia de una API REST, un hub no (solamente) responde a una petición, sino que puede enviar mensajes tanto al cliente que la ha realizado, a todos los clientes o al resto, en tiempo real, entre otras cosas.

Para definir un hub, solamente necesitamos una clase que herede de la clase Hub y SignalR hará el resto, es decir, descubrir los diferentes hubs y exponerlos al cliente.

Veamos un ejemplo, con el siguiente código en C#:


public class ChatHub : Hub
    {
        public void Send(string name, string message)
        {
            // Call the broadcastMessage method to update clients.
            Clients.All.broadcastMessage(name, message);
        }
    }

SignalR genera este código, que lo podemos ver acudiendo a la url http://miservicio/signalr/hubs:

 proxies.chatHub = this.createHubProxy('chatHub'); 
        proxies.chatHub.client = { };
        proxies.chatHub.server = {
            send: function (name, message) {
                return proxies.chatHub.invoke.apply(proxies.chatHub, $.merge(["Send"], $.makeArray(arguments)));
             }
        };

El hecho de que SignalR descubra de manera automática los hubs nos puede traer problemas cuando los hubs están en un ensamblado diferente al que está cargando SignalR (por ejemplo, si tenemos dos aplicaciones que usen exactamente el mismo tipo de hub).

Tras mucho buscar, la única solución que he encontrado para cargar los hubs desde otro ensamblado pasa por la siguiente línea:

AppDomain.CurrentDomain.Load(typeof(Namespace.ChatHub).Assembly.FullName);

Este código carga el ensamblado que contiene la clase para que SignalR “descubra” el Hub, y lo debemos situar justo antes de app.MapSignalR() o de lo contrario el Hub no se generará.

Ofuscación

Si distribuimos nuestra aplicación a nuestros clientes (por ejemplo ofrecemos una solución que contiene SignalR para que la puedan instalar en un servidor local) es habitual recurrir a herramientas como SmartAssembly o Dotfuscator, para proteger la propiedad intelectual de nuestro código.

Para que el funcionamiento de SignalR sea correcto, es importante recordar que no debemos ofuscar las clases Hub, ya que la clase se carga mediante reflexión, y la ofuscación provoca o bien que la clase no sea encontrada con su nombre original, o bien que no se pueda acceder a los métodos, o bien que, al no ser llamados por otras partes de nuestro código, se deseche. La mejor solución pasa por usar los hubs como una clase “pantalla” y ofuscar aquellas que sean llamadas desde el hub.

Para evitar la ofuscación podemos, o bien de manera manual en las propiedades del proyecto, o a través de atributos. En el caso de SmartAssembly encontramos atributos como [DoNotObfuscateType] y [DoNotPruneType] que se aplican a toda la clase, y en el caso de Dotfuscator contamos con el atributo [Obsufcation]

Más información

Angular.js para aplicaciones Windows Store

Existe una gran variedad de frameworks javascript, Angular, Ember, knockout, etc. Todos ellos nos proporcionan algo que aquellos que hemos hecho wpf estábamos esperando: Data binding, y la posibilidad de usar patrones como MVVM.

En este artículo doy un vistazo a Angular.js, un framework desarrollado por Google que está dando mucho de que hablar, y, para hacerlo más interesante, he lo empleo dentro del contexto de una aplicación Windows 8, donde las reglas del juego cambian ligeramente.

Instalación y configuración

Para este proyecto, el primer paso es crear una aplicación vacía de Windows 8 con Javascript, podemos usar Visual Studio Express para ello.

Para incluir Angular.js, una cosa que podemos pensar es enlazar directamente a la CDN de angular desde nuestro fichero default.html:

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js">
</script> 

Sin embargo nos encontramos con esto:

Usando la CDN de Angular JS

Es decir, no podemos usar una referencia no local para ficheros javascript con lo cual tendremos que descargarlo e incluirlo en nuestro proyecto manualmente. Podríamos además, estar tentados a instalarlo usando nuget, pero en mi opinión agrega demasiados archivos al proyecto.

Como anotación, recomiendo descargar la versión angular.js, no la angular.min.js, ya que tendremos que hacer algunos cambios más adelante.

Una vez tengamos el fichero agregado a nuestro proyecto, si intentamos compilar tendremos una segunda sorpresa:

Excepcion con angular

Hay muchas maneras de resolver este error, pero el que a mí me ha funcionado pasa por editar la función problemática, y sustituir la llamada a la función insertBefore por:

MSApp.execUnsafeLocalFunction(function ()
 {element.insertBefore(child, index);
});

Con este ligero cambio, ya podremos ejecutar nuestra aplicación.

Las vistas

Para mostrar información por pantalla, en vez de construir el HTML manualmente y editar el DOM desde código javascript, simplemente usamos ciertas convenciones para incrustar datos dentro de una plantilla HTML.

<label>Name:</label>
<input type="text" ng-model="yourName" 
placeholder="Enter a name here" />
<h1>Hello {{yourName}}!</h1>

En este caso, el input genera una variable de nombre yourName, que se actualiza en el campo h1, en la región habilitada para ello. Estas variables encerradas entre llaves se pueden usar también dentro de los elementos html, por ejemplo para fijar la propiedad “src” de una imagen:.

<img src="{{item}}" />

No tenemos que preocuparnos por la actualización, ya que al cambiar el contenido del dato, sea cual sea, el valor será actualizado automáticamente. Esto representa una diferencia bastante interesante respecto a otros frameworks como Knockout, donde para que se actualizara el objeto teníamos que definirlo con un tipo muy específico.

Controladores

El controlador se define como una clase javascript, con propiedades y funciones, las cuales luego suelen ser llamadas desde el código fuente, por ejemplo:


function TodoCtrl($scope) {
$scope.todos = [];

$scope.addTodo = function () {
$scope.todos.push({ text: $scope.todoText, done: false });
        $scope.todoText = '';
};

};

En este ejemplo se define un controlador, un campo llamado todos, y un método para almacenar en la lista el valor definido en la variable todoText. El $context es similar al this del standard, aunque con algunas variantes. La vista de este código se parece a algo así:

<h2>Todo</h2> {{todos.length}}
<form ng-submit="addTodo()">
    <input type="text" ng-model="todoText" placeholder="add new todo here" size="30" />
    <input class="btn-primary" type="submit" value="add" />
</form>

A diferencia de lo visto anteriormente, en este código definimos un controlador, accedemos al campo length del objeto todos definido anteriormente, y finalmente llamamos al método como resultado del envío de formularios.

Bucles (y bucles dentro de bucles)

Otra de las cosas interesantes que tiene, es el uso de los bucles para recorrer información:

<ul>
    <li ng-repeat="todo in todos">
        <p>{{todo.name}}</p>
        <span ng-repeat="item in todo.items">
            <img src="{{item}}" /></li>
    </li>
</ul>

En este caso representamos la estructura de todos, y asumiendo que todo es una estructura compuesta, Estos bucles además se pueden anidar, consiguiendo una mayor libertad a la hora de representar datos complejos.

Llamadas HTTP

Para poder hacer llamadas a un servidor externo mediante http solamente necesitamos la url y el método por el cual realizaremos la petición, para efectuar la llamada de la siguiente manera:


$http({ method: 'GET', url: 'http://url' }).
 success(function (data, status, headers, config) {

}).
 error(function (data, status, headers, config) {

});

Este código lo incluiremos en nuestro controlador sin llamadas adicionales, de tal manera que sea ejecutado al cargar el controlador. Si lo hacemos de esta manera nos encontraremos con un bonito error como el que se muestra a continuación:

Http error

Para evitar ese error, hemos de modificar la definición de nuestro controlador:

function TodoCtrl($scope)

De tal manera que ahora además de $scope, recibe $http:

function TodoCtrl($scope, $http)

Resumen

Esto es solamente una primera toma de contacto, y he de decir que la primera impresión ha sido muy buena. La documentación y la cantidad de ejemplos disponibles en internet ayudan también a que la curva de aprendizaje sea simple.

Enlaces adicionales

Moving windows programatically with Windows API, the path to WinResize

When we test VS Anywhere in a production environment, one of the things that we tend to do is to open 2 sessions of Visual Studio on either side of the screen, so we can make quick tests of specific features.

goal

This requires opening 2 different instances of visual studio by hand, and attach each side of the screen, something tedious, boring, and, above all, automatable. So I set out to find the way of solving this small issue.

The path

If we have Windows 7 or higher we can make use of Aero Snap, using Win+Left or Win+Right, it sets a window to the left or to the right of the screen. It seemed simple, I would only need to emulate this key combination, something that it seemed easy to do:

Theorically, we can solve this by using Powershell. In fact, in the following entry of TechNet Provide Input to Applications with PowerShell explains how to send commands to an application using SendKeys, resulting in the following code:

add-type -AssemblyName microsoft.VisualBasic
add-type -AssemblyName System.Windows.Forms
Calc
start-sleep -Milliseconds 500
[Microsoft.VisualBasic.Interaction]::AppActivate("Calc")
[System.Windows.Forms.SendKeys]::SendWait("1{ADD}1=")

According to the last line, we should be able to send to the program any combination of keys, so the next step was to find the Windows key in the SendKeys reference: http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send(v=vs.110) .aspx

Surprise: is not there. On the other hand, looking a bit online, I found that the Windows keystroke could be simulated by using the Ctrl + Esc.

Second surprise:  IT SIMULATES the WINDOWS key, and nothing else. When you press that combination, It jumps right to the desktop or to the start menu, it is not possible to use it to simulate a key combination involving Win + whatever, so that by this way little more we can do.

On the other hand, if what we are doing is a keyboard shortcut, surely matches some kind of command available on the Windows API that makes the action of Aero Snap, but no, there is no API, no documentation and there is no reference except the brand name, so this is another dead end.

There was still another option, which was to move the window directly using a custom program, after some search I found this piece of code, allowing you to do what I wanted using Powershell:

It was not too complex, but I chose to do a small application with C# so that it could solve the problem, using native calls to the Windows API through P/Invoke:

Importing functions and moving windows

To use the Windows API functions we have to copy their header in our function, define it as external (.NET framework will already know what to do) and define the DLL from which we import, in this case the function MoveWindow is located in user32.dll:

[DllImport ("user32.dll")]
public static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);

We will have to repeat this process for each function that we want to import, a we will also need to add the following using:

using System.Runtime.InteropServices;

To be able to move the window, we need its hWnd, which is a unique window identifier. There are many ways to locate it, and one of them is from the list of processes, selecting those whose main window matched with what was looking for, in this case “Visual Studio”.

foreach (Process proc in Process.GetProcesses ()
{
    if (proc.MainWindowTitle.Contains ("Visual Studio"))
    {
        IntPtr handle = proc.P:System.Diagnostics.process.MainWindowHandle;
        ...
        MoveWindow(handle...);
        ...
    }
}

For moving the window, we need to set an origin and a size, and for this we could either fix them manually, or rely on the resolution of the screen, using the following functions:

Screen.PrimaryScreen.WorkingArea.Width;
Screen.PrimaryScreen.WorkingArea.Height;

These are found within the namespace System.Windows.Forms, which requires in addition a reference as System.Drawing from our project.

The really interesting thing about this, is that it allows us to move the window to the position we would like with any size, so we can take advantage of it in order to set any number of windows, being these equally distributed.

Finally we need a couple of additional calls to Windows API functions to maximize the window before moving it, and to set the focus, which are imported in a similar way:

[DllImport ("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int X);
[DllImport ("user32.dll")]
public static extern bool SetFocus(IntPtr hWnd);

Launching applications and input parameters

In addition to the functionality of moving windows, it could be interesting to launch the apps we want to move, so a bit of extra code to generate a process, to set the name of the file, and, after launching it, a small sleep while loading:

Process p = new Process();
p.StartInfo.FileName = "notepad.exe";
p.Start ();
System.Threading.Thread.Sleep (2000);

To make it simpler, the last step is to convert all the parameters used to input arguments of the program, being finally the project a console application, which gets, in this order;

  • Path of the executable
  • Title of the window to search
  • Number of processes to launch
  • Waiting for each process

In the case of a 3 windows launch for notepad.exe, this is the output showing the console application:

WinResize

On the other hand we have 3 windows, equally distributed:

Result

As the last detail, the window title is set using the following code block:

Console.Title = "WinResize";

Wrapping up

This is a small app that solves a very specific scenario can be widely improved and I’ll probably work for some more time on it, here are some ideas for future improvements:

  • Make all the script in powershell, it’s possible, and we can make P/Invoke without problems
  • Emulate the keypress (must be a code associated with the windows key, and a way to press it!) simulating the keyboard.
  • Rather than take all processes available, use the ID of those we’ve just created.

The code is available for free and licensed under open source. If you want to contribute please send your pull request :)

Enjoy!

Additional links