Las apps de SharePoint 2013 (IV): Una app en MVC y en Azure
February 12, 2013
En la serie de posts sobre el desarrollo de apps de SharePoint 2013, hasta ahora hemos visto como se desarrolla una app sencilla y alojada en SharePoint (es decir, las “SharePoint-hosted” apps). Ahora vamos a subir un poco la dificultad (no mucho, os lo prometo) y vamos a hacer una app que se ejecuta fuera de SharePoint.
Para que el ejemplo sea más interesante, vamos a hacerlo en un “sabor” de ASP.NET al que no estamos tan acostumbrados los SharePointeros: ASP.NET MVC 4. Como la app fuera de SharePoint puede estar escrita en cualquier lenguaje que se nos antoje, usaremos MVC 4 para aprovecharnos de la librería de modelo de objetos de cliente de SharePoint 2013 (CSOM) y ahorrarnos trabajo.
SharePoint 2013 y Azure
En estos momentos Microsoft ofrece una cuenta de desarrollador de Office (incluyendo SharePoint) gratis si nos apuntamos en este enlace. Con ello se nos dará un sitio en Office 365 Preview (es decir la versión 2013) ya preparado para alojar apps de SharePoint 2013. Además, se nos dará una cuenta “invisible” en Azure para nuestras apps. Digo que es invisible porque no hay manera (de momento) de gestionar la suscripción para estas apps.
Para las apps que se consideran “Autohosted”, Visual Studio 2012 con las herramientas de SharePoint va a hacer una doble función:
- Si estamos desarrollando y le damos a F5, VS2012 va a subir el descriptor de nuestra app a la cuenta de Office 365 de desarrollador (esto lo configuramos nosotros en el proyecto de app) pero la apuntará a nuestro localhost donde se ejecutará el proyecto web de ASP.NET que contiene la lógica de la app.
- Si hacemos un Deploy de la solución, VS2012 subirá el descriptor de la app a Office 365 (como antes) pero además subirá el proyecto web a un subdominio de o365apps.net, que es una suscripción especial de Azure Web Sites disponible a nosotros como desarrolladores de la app. El subdominio será un GUID creado de manera automática al deployar la app. Además, va a cambiar el descriptor de la app para que apunte a Azure y no a nuestro localhost.
Vale la pena recalcar que la suscripción “invisible” de Azure para apps de Office/SharePoint sólo incluye Web Sites (un hosting de IIS, vamos) y SQL Azure (mediante scripts), sin incluir nada de Media Services, Mobile Services, Storage, Compute y otras maravillas de Azure.
La app en Azure y MVC, paso a paso
Para que todo esto resulte más fácil de digerir, vamos a hacer un pequeño ejemplo que muestre las listas y bibliotecas que hay en el SharePoint donde está alojada la app. Lo codificaremos en MVC 4 y lo “subiremos automágicamente” a Azure. El prerrequisito es, como siempre, tener instaladas las herramientas de desarrollo de SharePoint 2013 con Visual Studio 2012 y tener la suscripción de desarrollador de Office 365.
Abrimos Visual Studio 2012 como Administrador y creamos un proyecto nuevo de Aplicación de SharePoint 2013. Le decimos a VS2012 que la app es de tipo Autohosted y le pasamos la URL de nuestro Developer Site de Office 365.
Visual Studio creará dos proyectos: el de la app (EdinSpMvc, poco más que un manifest) y el proyecto ASP.NET WebForms (EdinSpMvcWeb) con la parte de la app que se ejecuta fuera de SharePoint. Como podéis ver, contiene una página Default.aspx de toda la vida.
Como esta basura tecnología no nos interesa, vamos a agregar otro proyecto web, esta vez una aplicación web de MVC 4. Es importante seleccionar NET Framework 4 en vez de 4.5 que nos sale por defecto, ya que el Azure que nos da Office Developer no tiene todavía soporte para NET 4.5. A continuación, elegimos Basic como plantilla por defecto de la aplicación MVC.
Ya tenemos 3 proyectos: el de la app, el de web ASP.NET y el de web MVC 4.
Vamos a configurar el proyecto web MVC con algunos detallitos para que funcione bien con SharePoint 2013. Tenemos la suerte de que las herramientas de VS2012 ya lo hacen automáticamente por nosotros.
Primero, vamos a las propiedades del proyecto de app de SharePoint para asociar el proyecto web MVC en la propiedad Web Project. En este momento VS2012 nos preguntará si queremos que nos adjunte las referencias de SharePoint y que quite la página por defecto, a lo de que vamos a contestar que sí.
Fijaos que el proyecto MVC ahora tiene las referencias de SharePoint 2013 y de Identity Framework, así como el fichero auxiliar TokenHelper.cs que nos ayudará a hacer la autenticación contra SharePoint. Además, la propiedad SSL Enabled del proyecto MVC está puesta a True porque es necesario HTTPS para que funcione el paso de credenciales.
Por último, hay que corregir la Start URL de la app (que apunta ahora a EdinSpMvc4Web/Pages/Default.aspx) editando el fichero AppManifest.xml del proyecto de app de SharePoint. Ponemos EdinSpMvc4Web/Home para apuntar al controller Home.
Podemos eliminar el proyecto de ASP.NET WebForms, porque ya no lo necesitamos.
Ahora vamos a agregar la “chicha”, la lógica de negocio en nuestra aplicación MVC. Para ello crearemos un controller nuevo llamado HomeController y una vista asociada llamada Index en su carpeta ViewsHome.
En la acción Index del HomeController, vamos a ponerle el siguiente código, sin olvidarnos de poner la clausula using Microsoft.SharePoint.Client:
> var contextToken = TokenHelper.GetContextTokenFromRequest(System.Web.HttpContext.Current.Request);
> var hostWeb = System.Web.HttpContext.Current.Request\["SPHostUrl"\];
>
> using (var clientContext = TokenHelper.GetClientContextWithContextToken(hostWeb, contextToken, Request.Url.Authority))
> {
> var web = clientContext.Web;
>
> clientContext.Load(web, w => w.Lists.Include(l => l.Title).Where(l => !l.Hidden));
> clientContext.ExecuteQuery();
> clientContext.Dispose();
>
> return View(web.Lists);
> }
En este ejemplo lo que hacemos es obtener el token de contexto (proporcionado por SharePoint 2013 al redireccionar a la app en Azure) y con este token de contexto abrimos un contexto de cliente (lo que necesitamos para usar el modelo de objetos de cliente de SharePoint 2013). Fijaos que no estamos proporcionando ninguna credencial de cliente, sino que la propia app se autentica contra SharePoint.
Ahora nos falta hacer que la vista muestre las listas que le hemos pasado en la acción. Abrimos la vista y le añadimos:
> @{
> ViewBag.Title = "App de SharePoint con MVC";
> }
>
> <div>
> <ul>
> @foreach (var list in Model)
> {
> <li>@list.Title</li>
> }
> </ul>
> </div>
Con este código conseguimos que la vista muestra las listas que le pasa el controlador. Le damos a F5 y nuestra app se ejecuta en SharePoint 2013 pero apuntando a nuestro localhost:
Confirmamos que nuestra app es de confianza…y vemos la app ejecutándose en MVC (en nuestra máquina):
Para los curiosos: el VS2012 ha agregado un ClientId y ClientSecret a nuestro web.config automáticamente (y también los ha registrado en el servidor de SharePoint). De esta manera la llamada de nuestra aplicación MVC a SharePoint está autorizada porque se basa en un ID y secreto conocidos por SharePoint.
El último paso que nos queda es darle un poco de aspecto de SharePoint a la app, cambiando la “master” (la vista _layout.cshtml) para incluir la barra de herramientas de SharePoint 2013.
En la sección BODY añadiremos un DIV a modo de “placeholder” donde insertaremos la barra de herramientas.
<div id="barraSharePoint"></div>
En la sección HEAD, debajo de la referencia a @Scripts.Render("~/bundles/modernizr"), agregaremos el código siguiente:
<script type="text/javascript" src="[https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js"](https://ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js%22)\></script>
<script type="text/javascript" src="[https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js"](https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js%22)\></script>
<script type="text/javascript">
var hostweburl;
$(document).ready(function () {
hostweburl = decodeURIComponent(getQueryStringParameter("SPHostUrl"));
var scriptbase = hostweburl + "/\_layouts/15/";
$.getScript(scriptbase + "SP.UI.Controls.js", renderChrome)
});
function renderChrome() {
var options = {
"appIconUrl": "/Content/Images/user-logo.png",
"appTitle": "@ViewBag.Title",
"settingsLinks": \[
{
"linkUrl": "[http://spblogedin.blogspot.com"](http://spblogedin.blogspot.com%22/),
"displayName": "Blog de Edin"
}
\]
};
var nav = new SP.UI.Controls.Navigation("barraSharePoint", options);
nav.setVisible(true);
}
function getQueryStringParameter(paramToRetrieve) {
var params =
document.URL.split("?")\[1\].split("&");
var strParams = "";
for (var i = 0; i < params.length; i = i + 1) {
var singleParam = params\[i\].split("=");
if (singleParam\[0\] == paramToRetrieve)
return singleParam\[1\];
}
}
</script>
Lo que hace este código es obtener la URL del SharePoint (el parámetro SPHostUrl) y llamar a su script SP.UI.Controls.js que se encarga de dibujar la UI. Lo llamamos desde SharePoint mediante una llamada a $.getScript (para evitar el problema de JS cross-domain) y en la función de callback pintamos una barra (un control SP.UI.Controls.Navigation). Para construir este control le pasamos un objeto JS con las propiedades que van a controlar la manera en la que se va a dibujar. He aprovechado también para agregar un pequeño logo para la aplicación, creando una carpeta Images dentro de Content en el proyecto MVC y subiendo el logo por defecto de una aplicación de LightSwitch.
Ahora ya estamos preparados para hacer un Deploy Solution en vez de un F5. Se nos vuelve a abrir una instancia del navegador pidiendo autorización para la app. La sorpresa es que esta vez nuestra aplicación de MVC está en el sitio web de Azure para Office Developers (dominio o365apps.net), como podéis observar:
Además, la aplicación ahora tiene una pinta más “SharePointera” y con un menú de control que tiene el enlace a este blog
Os dejo el código fuente en mi SkyDrive, por si no tenéis ganas de escribir código, jeje.
En la próxima entrega de esta serie veremos como hacer una aplicación Provider-hosted en Azure, con lo que podemos aprovechar todos los servicios que nos ofrece Azure para construir nuestra app.