Windows Phone 7: Primeros pasos

Ya es más que conocida la importancia que tienen día a día los llamados mobiles inteligentes. Actualmente en el mercado compiten IPhone, Android y mas recientemente Windows Phone 7 (WP7). Para los que desarrollamos en .NET tenemos algunas alternativas en lo que se refiere al desarrollo de aplicaciones mobiles, por ejemplo, para desarrollar en Android podemos utilizar MonoDroid gracias a su extensión para Visual Studio 2010 (thanks @ihuro por el instalador). Pero en este post vamos a concentrarnos en WP7.

Es importante resaltar que Windows Phone 7 rompe con la forma en que anteriormente se venían desarrollando las aplicaciones Windows Mobile, muestra de ello es la compatibilidad que trae para trabajar con tecnologías modernas como ser Silverligth y XNA.

Para comenzar a trabajar con Windows Phone 7 vamos a descargar Windows Phone 7 Developer Tools Package. Este conjunto de herramientas ya se encuentran en su versión final e incluye todo lo necesario para poder desarrollar aplicaciones mobiles completas (es bueno decir que todo lo incluido en el packcage es gratis). Las herramientas incluidas en el instalador son: Visual Studio 2010 Express for Windows Phone, Expression Blend 4 for Windows Phone, Silverligth for Windows Phone, XNA Game Studio for Windows Phone, Windows Phone Emulator Phone Registration Tool.

Al ejecutar el instalador se nos va a preguntar si queremos comenzar la instalación directamente o si solamente queremos instalar algunas de las características antes mencionadas. Aclaro que la duración de la instalación dependerá básicamente de la conexión a Internet que tengamos, ya que deberemos descargar aproximadamente unos 400 Mb.

Instalando WP7 Tools

Instalando WP7 Tools

Finalizada la instalación nos aparecerá un botón para comenzar a utilizar las herramientas. En mi caso ya tenía previamente instalado Visual Studio 2010 por lo que me abrirá dicha versión (de lo contrario se abrirá la versión de Express for Windows Mobile) .

Bien, ahora vamos a ver que al crear un nuevo proyecto tendremos disponible tanto proyectos Silverligth como XNA para desarrollar aplicaciones WP7. Para constatar esto vamos a crear un proyecto del tipo Silverligth for Windows Phone: dentro de Visual Studio 2010 hacemos click en el menú  “File\New\Project…” y luego en la pestaña “Silverlitgh for Windows Phone” elegiremos el tipo de aplicación “Windows Phone Application“.

Creando nuestro primer proyecto WP7

Creando nuestro primer proyecto WP7

Creamos el proyecto y veremos en el IDE algunas cosas que nos van a resultar familiares para aquellos que programamos aplicaciones web en Silverligth o aplicaciones de escritorio con WPF, por ejemplo los archivos XAML App.xaml y MainPage.xaml.

Entorno de desarrollo

Entorno de desarrollo

No es la idea de este post analizar en profundidad como esta compuesta la aplicación, sino simplemente mostrar el proceso de instalación y la creación de un proyecto de prueba. Para finalizar ejecutamos la aplicación y veremos que se nos habre el emulador del mobil con nuestra app:

Corriendo nuestra aplicación en el emulador

Corriendo nuestra aplicación en el emulador

Listo, ahora ya tenemos preparado el entorno de desarrollo y podemos comenzar a trabajar en nuestras aplicaciones WP7.

Para tener información actualizada sobre WP7 pueden visitar http://developer.windowsphone.com.

Anuncios

ASP.NET MVC 3: Unobtrusive AJAX

Una de las características de ASP.NET MVC 3 relacionadas a las peticiones AJAX y a Javascript es “Unobtrusive AJAX”. Que quiere decir esto?… la traducción directa no es del todo clara, así que vamos a decir que básicamente se trata de realizar invocaciones AJAX sin necesidad de “meter” o “mezclar” código Javascript o jQuery dentro de nuestro HTML.

Antes de poder comenzar a utilizarlo debemos hacer una modificación en nuestro web.config para activar dicha funcionalidad. Para ello vamos a setear en true la key UnobtrusiveJavaScriptEnabled:

1: <appSettings> 
2:   <add key="UnobtrusiveJavaScriptEnabled" value= "true"/>  
3: </appSettings>

También podemos habilitar esta funcionalidad en contextos particulares y no de manera global. Para ello en lugar de modificar la entrada anterior en el web.config podemos hacerlo mediante código, por ejemplo en una vista agregando la siguiente linea:

1:  @{ HtmlHelper.UnobtrusiveJavaScriptEnabled = true;  }

También es importante agregar las referencias de los siguientes archivos de script en la vista:

1: <script src=" @Url.Content("~/Scripts/jquery-1.4.1.js")"  
2:         type="text/javascript"></script>
3: <script src=" @Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"
4:         type="text/javascript"></script>

Vamos a comentar rápidamente de que se tratan estos scripts. El primero de ellos es la librería de jQuery y el segundo es plugin de que nos provee el framework que nos permitirá trabajar con “Unobtrusive AJAX” en conjunto con jQuery utilizando para ello el helper de Ajax. Nota: anteriormente los AjaxHelper solo funcionaban con los scripts de la Microsoft Ajax Library.

Bien, ya tenemos todo configurado, para darnos una mejor idea de que se trata todo esto vamos a crear un vista desde la cual se podrá calcular la edad  de una persona ingresando su fecha de nacimiento.

Para esto vamos a crear un nuevo controlador llamado DateController y un método de acción Index() que nos va a generar el formulario en cuestión. También crearemos un método HttpPost que se invocará por Ajax al cual le pondremos como nombre CalcularEdad y que es el encargado de  calcular y retornar la edad a la vista:

1: public class DateController : Controller 
2: {
3:     public ActionResult Index()
4:     {
5:         return View();
6:     }
7:
8:     [HttpPost]
9:     public string CalcularEdad(DateTime fecha)
10:     {
11:         return string.Format("{0} años.", ObtenerEdad(fecha));
12:     }
13:
14:     private double ObtenerEdad(DateTime fecha)
15:     {
16:         double edad = DateTime.Now.Subtract(fecha).TotalDays / 365.25;
17:         return System.Math.Truncate(edad);
18:     }
19: }

La vista vamos a armarla de la siguiente forma, utilizando para ello el atributo Ajax (del tipo AjaxHelper) que nos provee el WebViewPage para dibujar el formulario:

1:  @{
2:     ViewBag.Title = "Index" ;
3:     Layout = "~/Views/Shared/_Layout.cshtml" ;
4:  }
5:
6: <script  src=" @Url.Content("~/Scripts/jquery-1.4.1.js")"  
7:         type="text/javascript"></script> 
8: <script  src=" @Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"  
9:         type="text/javascript"></script> 
10:
11: <h2> Calculador de edad</h2> 
12:
13:  @using  ((Ajax.BeginForm("CalcularEdad", 
14:                          new  AjaxOptions () { 
15:                             HttpMethod= "Post" , 
16:                             UpdateTargetId= "resultRegion" }
17:                         )
18:         ))
19: {
20:
21:     <label>Fecha de nacimiento:</label>  
22:     <input type="text" name="fechaNacimiento" id="fechaNacimiento"/> 
23:     <input type="submit" value="Calcular"  /> 
24: }
25: <hr/> 
26: <b>Usted tiene </b><div id="resultRegion" /> 
27: <hr/>
28:

Notemos que al crear el formulario estamos indicando como primer parámetro que método vamos a invocar al hacer el submit del mismo, y ademas seteando algunas opciones, como ser el tipo de invocación http (en nuestro caso POST ) y en que región del HTML queremos volcar el resultado (para este ejemplo dentro del div con id resultRegion).

Ejecutamos y vamos a obtener la siguiente vista, ingresando una fecha y presionando el botón “Calcular” obtendremos la edad sin necesidad de refrescar el contenido:

Vista resultante

Vista resultante

Si vamos a inspeccionar nuestro html notaremos que no posee ningún script!

HTML sin scripts

HTML sin scripts

Abran notado que los AjaxOptions que definimos en la creación del formulario por medio del objeto AjaxHelper que nos provee MVC se rendizaron con el nombre “data-”. Esto es porque HTML 5 reserva dichos atributos para el uso de scripts, por lo que ya nos permite tenerlo preparado para el caso que trabajemos con dicha versión de HTML.

Les dejo dos links muy interesantes y recomendables sobre el tema. El primero de Brad Wilson y el segundo de Eduard Tomàs i Avellana.

ASP.NET MVC 3: New ActionResult Types

Una de las nuevas caracteristicas que trae esta versión de ASP.NET MVC son tres nuevos tipos de ActionResults:

  • HttpNotFoundResult: se utiliza para indicar que un recurso no se encontró, el famoso código 404.
  • HttpRedirectResult: se utiliza para indicar si una re-dirección permanente debe ocurrir.
  • HttpStatusCodeResult: se puede utilizar para establecer un código derespuesta de estado y la descripción explícita.

Básicamente lo que hacen es viajar desde el controlador a la vista con un código de estado especifico (Response.StatusCode) que luego sera procesado por el servidor. Ahora veamos un ejemplo de cada uno:

HttpNotFoundResult

Veamos un ejemplo simple, vamos a crear un método de acción llamado Details que recibe como parámetro un Id de producto, trata de recuperarlo y en caso de no hacerlo devuelve un error Http 404:

1: public ActionResult Details(int  id)
2: {
3:     var product = BussinesLogic.GetProductById(id);
4:
5:     if (product == null)
6:     {
7:         return HttpNotFound();
8:     }
9:
10:     return View();
11: }

El método HttpNotFound() lo que hace es devolver un HttpNotFoundResult. El resultado es el siguiente en el caso de que el producto no exista:

Http 404

Http 404

Viendo esta pantalla me pregunte, porque no re-direcciona a la pantalla de error personalizada que había configurado?… la respuesta la tengo gracias a José María Aguilar que me comento que HttpNotFound() lo único que hace es modificar sobre el canal de salida (Response) el código de estado y la descripción. Por lo tanto desde el punto de vista del framework no es ningún error que se deba procesar atendiendo al <customErrors>. Esta situación no fue algo que me agrado demasiado, pero puede ser una buena alternativa cuando utilizamos servicios del tipo REST (es decir, cuando las peticiones sobre las acciones las realiza una aplicación cliente).

HttpRedirectResult

Este resultado de acción se utiliza si queremos devolver una redirección temporal (con el código de estado Http 302) o una redirección permanente (código de estado Http 301). El tipo de redirección se define en función de un parámetro booleano llamado permanent o invocando distintos métodos como veremos a continuación.

Con la nueva versión del framework, la clase Controller ahora tiene tres métodos que devuelven una instancia de RedirectResultRedirectPermanent, RedirectToRoutePermanent RedirectToActionPermanent.

Veamos un ejemplo de una redirección permanente utilizando el método RedirectPermanent:

1: public ActionResult Details(int id)
2: {
3:     var  product = BussinesLogic.GetProductById(id);
4:
5:     if  (product == null)
6:     {
7:         return RedirectPermanent("/Product/Index");
8:     }
9:
10:     return View();
11: }

Básicamente lo que estamos haciendo es que en el caso de no encontrar un producto redireccionar al Index de los mismos. Si inspeccionamos el acceso a la acción Details con un Id inexistente el resultado sera un error 301 y la redicción a la pantalla principal de productos:

Http 301

Http 301

HttpStatusCodeResult

Este último ActionResult nos permite definir a nosotros el código de estado que queremos retornar como respuesta. En nuestro caso vamos a retornar el código Http 204 (el cual indica que el servidor ha recibido y aceptado la solicitud, pero entiende que no es preciso servir ningún documento como respuesta). En nuestro ejemplo, en el caso de que no exista el producto no es necesario mostrar información alguna, por lo tanto queremos permanecer en la pantalla actual.

1: public ActionResult Details(int  id)
2: {
3:     var product = BussinesLogic.GetProductById(id);
4:
5:     if  (product == null)
6:     {
7:         return new HttpStatusCodeResult(204, "No existe contenido.");
8:     }
9:
10:     return View();
11: }

Ejecutamos y veremos nuestro código de estado al intentar acceder al detalle de un producto inexistente:

Http 204

Http 204

El servidor no nos lleva a la pantalla de detalle del producto debido al código que le retornamos, por lo tanto quedaremos en la pantalla desde la cual quisimos acceder.

Espero que le sea de utilidad!