Windows Phone 7 y WCF

 

Introducción

Windows Phone 7 y Windows Communication Foundation forman un excelente dúo.

Debido a la gran orientación de Windows Phone 7 hacia la nube y a la falta de soporte oficial de bases de datos en el teléfono necesitamos encontrar una forma de almacenar nuestros datos fuera del dispositivo. Para esto, Windows Communication Foundation nos ofrece una plataforma segura, robusta y completa que cubrirá todas nuestras necesidades de comunicación con el exterior.

Dada la extensión y potencia de WCF a veces puede ser un poco complicado el hacer que todo funcione correctamente, con esto en mente creamos este artículo para guiaros por los pasos necesarios para llevar a buen término el uso de WCF con Windows Phone 7.

Creación del servicio

A la hora de crear servicios WCF para ser consumidos desde Windows Phone 7 no debemos tener ninguna consideración especial en cuenta, bastará con crear un servicio WCF standard, desde el menú Archivo > Nuevo > Proyecto (File > New > Project) en Visual Studio 2010 y en la pantalla de nuevo proyecto, seleccionar WCF de la lista de plantillas y WCF Service Application de los proyectos WCF disponibles.

image

 

Configuración del servicio

Una vez creado nuestro servicio WCF podremos desarrollarlo de forma normal, atendiendo a ciertas restricciones de configuración o características no soportadas actualmente por Windows Phone 7, a continuación tenemos una tabla en la que podemos ver una comparación entre el soporte de WCF que nos ofrece Windows Phone 7, y las versiones de escritorio de Silverlight (3 y 4):

Característica Versión

WP7

Silverlight 3

Silverlight 4

Bindings HTTP

X

X

X

Comunicación Duplex

 

X

X

Sindicación Rss

 

X

X

Bindings Custom

 

X

X

DataContract Serialization

X

X

X

Seguridad HTTPS

X*

X

X

JSON

 

X

X

Sockets

 

X

X

Seguridad BasicHttp

X

X

X

Proxy dinámico

 

X

X

* Solo disponible con ciertas entidades certificadoras: http://msdn.microsoft.com/en-us/library/gg521150(v=VS.92).aspx

Como podemos observar, en estos momentos Windows Phone 7 soporta las características básicas de WCF, podemos ver una descripción en profundidad del soporte que tenemos disponible para realizar servicios WCF en este enlace.

Una característica de los binding HTTP que tenemos disponible en WCF para Windows Phone 7 y es muy importante conocer es la sección ReaderQuotas. Esta sección de los binding HTTP indica los límites de tamaño bajo los que se tienen que mantener las peticiones al servicio para ser aceptadas o el tamaño máximo de un array que intentemos enviar. Por defecto el tamaño máximo de array está establecido en 16384, con lo que, por ejemplo, si intentamos enviar un array de bytes que contenga más elementos que 16384 el servicio denegará la petición.

Esta característica está pensada para proteger a nuestro servicio de un posible ataque DOS (Denial of service) que basándose en mensajes complejos intente colapsar los endpoints del servicio WCF. Debido a esto, debemos recordar siempre intentar ajustar los valores de esta sección en la medida de lo posible a los datos que vayamos a recibir, si ajustamos estos parámetros a un valor Max.Int32 estaremos eliminando esta defensa natural que tiene nuestro servicio.

Para configurar esta característica podemos usar la Herramienta de Configuración de Servicio WCF que tenemos disponible en Visual Studio 2010 en el menú Herramientas.

image

Simplemente debemos crear un nuevo binding para nuestro EndPoint y podremos ver la sección ReaderQuotas con los diferentes parámetros que debemos configurar como máximos bytes por lectura o longitud máxima de un array.

Una vez modificados los valores debemos aplicar la configuración a nuestro Endpoint:

image

Y ya solo nos queda guardar el trabajo que hemos realizado y veremos los valores reflejados en el archivo web.config de nuestro servicio:

  <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="NewBinding0">
          <readerQuotas
              maxDepth="128"
              maxStringContentLength="1024"
              maxArrayLength="131072"
              maxBytesPerRead="524288"
              maxNameTableCharCount="4">
          </readerQuotas>
        </binding>
      </basicHttpBinding>
    </bindings>
    <services>
      <service name="WcfService.Service1">
        <endpoint
              address="basichttp"
              binding="basicHttpBinding"
              bindingConfiguration="NewBinding0"
              name="basicHTTP"
              contract="WcfService.IService1">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

Con esto ya hemos visto cómo crear y configurar nuestro servicio y las restricciones que encontraremos al desarrollarlo para Windows Phone 7, el siguiente paso es conectar nuestra aplicación con nuestro servicio.

Conectando desde Windows Phone 7

El paso necesario para referenciar a un servicio WCF desde nuestra aplicación Windows Phone 7 es realmente simple.

Simplemente haremos click con el botón derecho del ratón sobre nuestro proyecto Windows Phone 7 y seleccionaremos la opción Añadir referencia a servicio (Add Service Reference)

image

 

Si el servicio WCF que deseamos referenciar se encuentra en la misma solución que nuestra aplicación, nos bastará presionar el botón Discover (Descubrir) para que en la lista de servicios aparezca el mismo. Si no es así, deberemos especificar la URL donde se encuentre el servicio WCF y presionar el botón Go (Ir).

Una vez hecho esto, solo tenemos que seleccionar el servicio, indicar el nombre de Namespace que deseamos asignarle y presionar OK para que Visual Studio 2010 se encargue de generar un proxy automáticamente para que tengamos acceso a todos los métodos y clases de nuestro servicio.

Solo tendremos que crear una instancia nueva de la clase que deseemos usar, y podremos acceder a los métodos del servicio, observaremos que el servicio expone métodos asíncronos para todos los métodos que hemos creado puesto que en Windows Phone 7 las peticiones web son asíncronas:

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            ServiceReference1.Service1Client proxy = new ServiceReference1.Service1Client();
            
            proxy.GetDataCompleted += new EventHandler<ServiceReference1.GetDataCompletedEventArgs>(proxy_GetDataCompleted);

            proxy.GetDataAsync(25);
        }

        void proxy_GetDataCompleted(object sender, ServiceReference1.GetDataCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                MessageBox.Show(e.Result.ToString());
            }
        }

Conclusión

Siguiendo los pasos citados en este artículo y leyendo los enlaces que hay a lo largo del texto podremos crear un servicio Windows Communication Foundation optimizado y una aplicación de Windows Phone 7 que haga uso del mismo de forma efectiva y sin problemas.

A continuación tenéis el código fuente completo para descargar, un saludo y Happy Coding!

Programación Asíncrona en Windows Phone 7

Hola a todos!

Una parte muy importante de la experiencia de usuario de nuestra aplicación móvil es la fluidez y rapidez con la que esta responde al usuario, todos hemos usado aplicaciones que ante cierta acción se quedan congeladas durante un periodo de tiempo antes de volver a responder, lo primero que pensamos es que la aplicación se ha bloqueado y la solución por la que optamos suele ser reiniciarla, aunque esperemos y la aplicación vuelva a ser operativa nuestra impresión hacia la usabilidad de la misma suele ser negativa. Además de esto, en Windows Phone 7 uno de los requerimientos para que nuestro desarrollo supere la aceptación en el marketplace es que la interface de usuario (UI) nunca se “congele”, siempre responda al usuario.

Para llevar a cabo esto, podemos hacer uso de distintos mecanismos de programación asíncrona incluidos en el framework de .NET 4, en esta ocasión vamos a ver como usar la clase BackgroundWorker para obtener de forma sencilla ejecución asíncrona en nuestra aplicación.

Hilos en Windows Phone 7

Toda aplicación Silverlight para WP7 se compone por defecto de dos Hilos:

  • Hilo de Interface de usuario: Es el hilo principal de nuestra aplicación, se encarga de manejar la entrada de usuario, procesar los objetos creados en XAML y ejecutar el resto de nuestro código.
  • Hilo de Composición: Se encarga de manejar tareas que normalmente serían responsabilidad del Hilo de UI, mejorando el rendimiento de las aplicaciones. Por ejemplo este hilo se encarga de procesar, combinar texturas gráficas y enviarlas a la GPU del dispositivo para que las dibuje, también se encarga de manejar las animaciones creadas con Storyboards, enviándolas automáticamente a la GPU y liberando así al hilo principal. Toda transformación realizada con los siguientes elementos se manejará en el hilo de composición:

Sin embargo el hilo de composición tiene limitaciones que pueden hacer que nuestra transformación pase a ejecutarse en el Hilo de UI, con el claro detrimento de rendimiento que experimentaríamos como consecuencia, para evitarlo en la medida de lo posible debemos tener en cuenta estos puntos:

  • Si para la Opacity usamos una máscara de opacidad, se procesará en el hilo de UI.
  • Si queremos hacer Clip de un área no rectangular, se procesará en el hilo de UI.
  • Si establecemos un ScaleTransform mayor al 50% del tamaño, se procesará en el hilo de UI.

Es muy importante que tengamos estos simples puntos en mente e intentemos evitarlos en la medida de lo posible, cada milisegundo ganado en el Hilo de Composición nos aportará mayor fluidez en nuestra interface de usuario.

BackgroundWorker

La clase BackgroundWorker es el método más sencillo para ejecutar código en un nuevo hilo. Tiene incluida funcionalidad para cancelar el procesamiento asíncrono, notificar el progreso, ejecutar código en el nuevo hilo y notificar la finalización de la tarea. Se encuentra definida en el namespace System.ComponentModel.

Es muy sencillo trabajar con esta clase, básicamente, debemos crear un manejador para el evento DoWork, este manejador es el que se ejecutará en el nuevo hilo dedicado, disponemos del evento ProgressChanged, que podemos manejar y lanzar durante el progreso de nuestra operación con el método ReportProgress. Una vez que la ejecución ha terminado se lanza el evento RunWorkerCompleted que de nuevo se ejecuta en nuestro hilo principal, en el que podemos comprobar si el proceso termino con errores, si se cancelo o si termino correctamente.

Durante la ejecución de nuestro código en el evento DoWork (asíncrono) desde el hilo principal podemos llamar al método CancelAsync, haciendo esto, si comprobamos la propiedad CancellationPending desde nuestro código asíncrono, obtendremos su valor a true, lo que siginifica que el usuario ha solicitado la cancelación, simplemente deberemos establecer a True la propiedad Cancel de DoWorkEventArgs y salir del método lo antes posible, momento en el que se lanzará el evento RunWorkerCompleted y, comprobando la propiedad Cancelled de RunWorkerCompletedEventArgs obtendremos true y podremos responder de forma adecuada.

Vamos a ver esto pasos con código para que quede más claro, tengo un pequeño ejemplo, una aplicación que cada 1,5 segundos añade un item a un listbox indicando el progreso de la tarea, usando para todo ello la clase BackgroundWorker:

Primero tenemos que inicializar una nueva instancia, indicandole que soportamos notificar progreso y cancelación (de lo contrario, al intentar cancelar o informar del progreso recibiremos una excepción de tipo InvalidOperationException), también vamos a crear los manejadores de eventos para DoWork, ProgressChanged y RunWorkerCompleted:

BackgroundWorker worker = new BackgroundWorker();

worker.WorkerSupportsCancellation = true;
worker.WorkerReportsProgress = true;

worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);

 

A continuación incorporamos el código que deseemos ejecutar en el hilo asíncrono al evento DoWork (CUIDADO! este código no puede acceder directamente a la interface de usuario o recibiremos una excepción de Cross Threading inválido):

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i < 10; i++)
    {
        Thread.Sleep(1500);
        worker.ReportProgress(i*10);
        if (worker.CancellationPending)
        {
            e.Cancel = true;
            return;
        }
    }
}

 

¿Y que pasa si queremos actualizar un control desde este código? Bueno, para esto WPF/Silverlight y por supuesto Windows Phone 7 ponen a nuestra disposición el Dispatcher, que básicamente nos sirve para indicar a un control que deseamos que ejecute código por nosotros, en el ejemplo anterior podriamos usar el Dispatcher de la ventana para que añada un Item a nuestro Listbox, en vez de usar el método ReportProgress:

this.Dispatcher.BeginInvoke((Action)delegate()
    {
        listCurrentOP.Items.Add("Elemento añadido con dispatcher.");
    });

 

Simplemente estamos indicanto el código que queremos ejecutar, y la ventana se encargará de ejecutarlo por nosotros, además, al usar BeginInvoke (en Windows Phone 7 solo está disponible este método) la ejecución continua automáticamente sin esperar a que se ejecute el código indicado al Dispatcher, por lo que continuamos nuestra filosofía de que nuestra aplicación siempre sea “usable”.

Cada vez que llamamos al método ReportProgress pasandole un valor numérico se lanza el evento ProgressChanged en el que, por ejemplo, podemos actualizar un control progressbar que muestre al usuario el progreso de la tarea, ten en cuenta que este evento SI se ejecuta en el hilo principal,  por lo que podrás acceder a los controles sin ningún problema de Cross Threading:

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    listCurrentOP.Items.Add(string.Format("Progreso: {0}.", e.ProgressPercentage));
}

 

Por último, una vez que el evento DoWork a terminado, se lanza el evento RunWorkerCompleted, donde podremos controlar posibles errores, cancelaciones o que todo ha funcionado correctamente:

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    StartWorker.IsEnabled = true;
    if (e.Cancelled)
    {
        listCurrentOP.Items.Add("Cancelado por el usuario.");
        return;
    }
    if (e.Error != null)
    {
        listCurrentOP.Items.Add("Error.");
        return;
    }

    listCurrentOP.Items.Add("Completado.");
}

 

Y listo! ya tenemos ejecución asíncrona en nuestras operaciones más pesadas, con cancelación, notificación de progreso y notificación de terminación, además el uso de la clase BackgroundWorker no es nada complicado.

 Os dejo para que podáis descargar el proyecto usado en este ejemplo, en Visual Studio 2010 para Windows Phone 7.

Un saludo a todos, gracias por leerme y Happy Coding!

[WP7] Actualización del kit de desarrollo para Windows Phone 7

winphone

Hola a todos!

Ya tenemos con nosotros una nueva actualización de las herramientas de desarrollo de Windows Phone 7, vamos a dar un vistazo a que nos ofrecen.

Lo primero… para todos los que esperábamos una sorpresa por parte de Microsoft en forma de nuevas APIs: Hay que seguir esperando, por el momento este update no nos ofrece nuevas APIs como la tan deseada captura de video en vivo y que, a mi parecer, tanta falta le hace a la plataforma, quizás incluso más falta que la multitarea.

¿Que nos trae de nuevo este emulador entonces?

Básicamente, este update nos ofrece Copy & Paste en nuestro emulador (por fin!), aunque con restricciones, solo se podrá copiar texto desde los controles TextBox, PasswordBox y WebBrowser, por lo que si queremos mostrar un texto susceptible de ser copiado por el usuario deberemos usar alguno de estos controles. De forma ideal, los desarrolladores deberíamos tener acceso a un API que nos permitiese meter texto en el portapapeles, pero por ahora, no existe tal API, por lo que deberemos adaptarnos a estos controles para usar el copy & paste.

El emulador en si mismo es mucho más rápido, se nota sobre todo en un fresh start, cuando arrancamos el emulador desde cero, tarda mucho menos tiempo en cargar y hacer el deploy desde Visual Studio.

Por otro lado, hasta ahora teníamos un problema a la hora de depurar aplicaciones que hiciesen uso de la radio u otras APIs multimedia, al intentar depurar estas aplicaciones con el Zune ejecutándose obteníamos una excepción de seguridad, pero si cerrábamos Zune no podíamos depurar nuestra aplicación desde Visual Studio. En este update se incluye una nueva herramienta llamada Windows Phone Connect que nos permitirá conectar a nuestro dispositivo desde Visual Studio con el software Zune cerrado y podremos depurar nuestras aplicaciones multimedia sin contratiempo. Esta herramienta la podemos encontrar en ProgramFilesMicrosoft SDKsWindows Phonev7.0ToolsWPConnect. Podéis encontrar una descripción y más detalles de su uso aquí

También tenemos una nueva herramienta llamada Capability Detection Tool  ubicada en ProgramFilesMicrosoft SDKsWindows Phonev7.0ToolsCapDetect que nos permitirá detectar las capacidades del teléfono que requiere nuestra aplicación y reemplazar las creadas por defecto. Más información aquí

Es importante saber que las aplicaciones existentes compilan correctamente sin necesidad de realizar ningún cambio y que la funcionalidad de copy & paste es nativa del sistema por lo que no tenemos que implementar nada nuevo en nuestra aplicación para hacer uso de ella, sin embargo si que nos avisan desde Microsoft que si un usuario intenta copiar un texto en un control dentro de un Pivot o Panorama, puede mover la pantalla sin quererlo, esto está solucionado en este update, pero si que nos exige recompilar y subir una actualización de nuestra aplicación a Marketplace para subsanar este comportamiento anómalo.

Por último he grabado un video del emulador arrancando desde cero y usando la característica de Copy & paste para que juzguéis por vosotros mismos si realmente ha mejorado en velocidad, espero que os guste.

Un vistazo rápido al emulador nuevo de WP7 & copiar/pegar

 

Un saludo y Happy Coding!

[Materiales] WebCast Extiende tu aplicación con Managed Extensibility Framework (MEF)

Hola a todos!

El pasado martes 1 de Febrero tuve el gran placer de unirme con la gente de SecondNug para hablar un rato sobre MEF, enseñar las posibilidades de extensión que nos ofrece y lo sencillo que resulta implantarlo en nuestras aplicaciones.

Para los que asististeis y para los que no pudisteis asistir ya está disponible tanto la grabación del evento como los materiales (ppt y demo vs2010) para descargar desde la web de SecondNug:

http://www.secondnug.com/EventosDesarrollo/tabid/57/Default.aspx

Muchas gracias a la gente de SecondNug por la ayuda para realizar el evento y la colaboración durante el mismo, ha sido una experiencia muy buena que espero repetir 🙂 y muchas gracias a todos los que asististeis por estar allí

Un saludo y Happy Coding!