Silverlight y ASP.NET MVC

Desde hace unos días, estoy hacienda una aplicación web un tanto simple que sirva para administrar los datos de otra aplicación móvil. Por lo cual se me ocurrió realizar una aplicación de una sola página, para así evitar que el usuario se tenga que moverse entre páginas muy similares que restan usabilidad al sistema.
La primera opción para realizar tal tarea fue usar JavaScript junto con JQuery pero, en medio camino se empezó a complicar la cosa y tome la decisión de usar Silverlight para completar la tarea (en otro post expondré con mayor profundidad el por qué tome tal decisión).
Ya con la decisión tomada, solo queda ponerse manos a la obra, pero para el presente post solo realizare una pequeña introducción de como unir ASP.NET MVC y Silverlight ya que pretendo realizar otros post donde entraremos a más detalle.

Crear el entorno de Trabajo


Nuestro primer paso será crear una aplicación en ASP.NET MVC habilitando las opciones para utilizar HTML5 como opción predeterminada y usar Razor como motor de vistas de ASP.NET MVC:

Nuestro siguiente paso será crear nuestra aplicación en Silverlight, donde tendremos cuidado de que se adjunte a nuestro proyecto de ASP.NET MVC:

Manos a la Obra

Ya con el entorno de trabajo creado procedemos a agregar la aplicación el Silverlight a alguna de nuestras vistas, para nuestro caso, la agregaremos a la vista “About” que viene por defecto con el proyecto de ASP.NET MVC:
  
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2"
 width="800" height="600">
 <param name="source" value="../ClientBin/Widget.xap" />
 <param name="background" value="White" />
 <param name="minRuntimeVersion" value="4.0.60129.0" />
 <param name="autoUpgrade" value="true" />
 <a href="http://www.microsoft.com/getsilverlight/get-started/install/" style="text-decoration: none">
 <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight"
 style="border-style: none" />
 </a>
 </object>
 <script type="text/javascript" src="../../Scripts/Silverlight.js"></script>
 <script type="text/javascript">
  function onSilverlightError(sender, args) {
   var appSource = "";
   if (sender != null && sender != 0) {
   appSource = sender.getHost().Source;
   }

   var errorType = args.ErrorType;
   var iErrorCode = args.ErrorCode;

   if (errorType == "ImageError" || errorType == "MediaError") {
   return;
   }

   var errMsg = "Unhandled Error in Silverlight Application " + appSource + "
   ";

   errMsg += "Code: " + iErrorCode + " 
  ";
   errMsg += "Category: " + errorType + " 
  ";
   errMsg += "Message: " + args.ErrorMessage + " 
  ";

   if (errorType == "ParserError") {
    errMsg += "File: " + args.xamlFile + " 
   ";
    errMsg += "Line: " + args.lineNumber + " 
   ";
    errMsg += "Position: " + args.charPosition + " 
   ";
   }
   else if (errorType == "RuntimeError") {
    if (args.lineNumber != 0) {
     errMsg += "Line: " + args.lineNumber + " 
    ";
     errMsg += "Position: " + args.charPosition + " 
    ";
    }
    errMsg += "MethodName: " + args.methodName + " 
   ";
   }

   throw new Error(errMsg);
  }
 </script>

El código que se puede ver en la parte superior es el mismo código que se encuentra en el archivo, TemplateSilverligthApplication.html que se agrega por defecto a nuestra aplicación ASP.NET MVC cuando creamos un nuevo proyecto Silverlight, enlazado a un sitio ASP.NET exceptuando el hecho de que la ruta de la aplicación lleva ../ Ya que al estar nuestra vista en un subdirectorio debemos indicar en nuestro path relativo que suba un nivel para poder encontrar el binario de Silverlight.

El siguiente paso es crear el modelo de datos de nuestra aplicación, que será una clase simple llamada Friendship. Pero además no debemos de olvidar que debemos serializar nuestros datos en formato JSON para que los datos puedan ser consumidos con facilidad por nuestra aplicación Silverlight, por lo tanto nuestro modelo será algo así (El ensamblado que contiene las clases de soporte para la serialización para JSON, se llama System.Runtime.Serialization):
  
using System.Runtime.Serialization;
 
namespace TestSLV.Models
{
    [DataContract]
    public class Friend
    {
        [DataMember]
        public string nameFriend { get; set; }
 
        [DataMember]
        public string twitterFriend { get; set; }
    }
}

Nuestro último paso en el lado del servidor será, agregar un par de métodos a nuestro controlador principal (HomeController), que se encargaran de generar una cadena de texto con la información serializada en JSON de una lista de objetos del tipo Friend:
  
public string ListFriends( )
        {
            var friends = new List 
            { 
                new Friend{nameFriend="Andiria",twitterFriend="sysandy"},
                new Friend{nameFriend="Francisca",twitterFriend="none"},
                new Friend{nameFriend="Fabiana",twitterFriend="none"},
            };
 
            return SerializeToJsonString( friends );
        }
 
        private string SerializeToJsonString( object objectToSerialize )
        {
            using ( MemoryStream ms = new MemoryStream( ) )
            {
                DataContractJsonSerializer serializer =
                    new DataContractJsonSerializer( objectToSerialize.GetType( ) );
                serializer.WriteObject( ms, objectToSerialize );
                ms.Position = 0;
                using ( StreamReader reader = new StreamReader( ms ) )
                {
                    return reader.ReadToEnd( );
                }
            }
        }

Ya con toda la infraestructura del servidor completada, el siguiente paso será consumir la información entregada por el servidor desde nuestra aplicación en Silverlight, para lo cual agregaremos la misma clase Friend que teníamos en el lado del servidor para poder des-serializar la información que nos entrega el servidor. Luego procederemos a crear la vista de nuestra aplicación, agregando un DataGrid:
  
<Grid x:Name="LayoutRoot">
  <ScrollViewer x:Name="PageScrollViewer" Style="{StaticResource PageScrollViewerStyle}">
   <StackPanel x:Name="ContentStackPanel">
    <TextBlock x:Name="HeaderText" Style="{StaticResource HeaderTextStyle}" 
   Text="Home"/>
    <sdk:DataGrid AutoGenerateColumns="True" Height="120" Name="friendGrid" Width="304" ItemsSource="{Binding Path=Friends}" />
   </StackPanel>
  </ScrollViewer>
 </Grid>

Luego agregaremos un ViewModel llamado HomeViewModel que herede de la clase abstracta BaseViewModel, para después agregar los respectivos métodos para la des-serialización de los datos, como se ve a continuación (Para poder hacer uso del espacio de nombres System.Runtime.Serialization.Json debemos agregar a nuestro proyecto los ensamblados System.ServiceModel.Web, System.Runtime.Serialization y System.Runtime.Serialization.Json):
  
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Net;
using System.Runtime.Serialization.Json;
using System.Text;
 
namespace Widget.ViewModel
{
    public class HomeViewModel : BaseViewModel
    {
        public ObservableCollection Friends { get; set; }
 
        public HomeViewModel( )
        {
            this.Friends = new ObservableCollection( );
            GetDataFromServer( );
        }
 
        private void GetDataFromServer( )
        {
            var serviceUri = new Uri( "/Home/ListFriends", UriKind.Relative );
            var webClient = new WebClient( );
            webClient.OpenReadCompleted += openReadCompleted;
            webClient.OpenReadAsync( serviceUri );
        }
 
        private List DeserializeFriend( string jsonString )
        {
            using ( MemoryStream ms = new MemoryStream( Encoding.Unicode.GetBytes( jsonString ) ) )
            {
                DataContractJsonSerializer serializer = new DataContractJsonSerializer( typeof( List ) );
                return (List) serializer.ReadObject( ms );
            }
        }
 
        private void openReadCompleted( object sender, OpenReadCompletedEventArgs e )
        {
            if ( e.Error != null )
                return;
 
            using ( StreamReader reader = new StreamReader( e.Result ) )
            {
                List temporal = DeserializeFriend( reader.ReadToEnd( ) );
                foreach ( Friend item in temporal )
                {
                    this.Friends.Add( item );
                }
            }
        }
    }
}

Con toda la infraestructura lista, lo único que resta realizar es lanzar nuestra aplicación y ver qué tal va:

Con la imagen de la aplicación corriendo, me despido
Suerte!
PD.- El tema de aplicación en Silverlight, se llama Cosmopolitan y lo pueden obtener de aquí.
Source: ASPandSVL.rar

Comentarios

  1. bien ahi gus...!!!
    xD *feel like a troll*... Typo Detected -> "hacienda" ... y amm =P interesantes los datos de ejemplo q ingresas xD.. =P
    Saludos Gush!

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Conectarse a un Web Service en PHP con WPF

Ejecutar comandos en el CMD de Windows desde C#

Usar Log4Net en un proyecto ASP.NET MVC