master Un punto diferenciador de SharePoint, con respecto a otras plataformas de colaboración, es la capacidad de ofrecer una capa de abstracción en cliente, permitiendo el desarrollo de aplicaciones o integraciones externas. Desde el primer día, los servicios Web de SharePoint han permitido interactuar con la plataforma de una forma sencilla y universal, permitiendo, sin tener que desarrollar ninguna API de servidor, acceder a cualquier tipo de contenido en SharePoint.
Con SharePoint 2010, se incluyeron dos opciones nuevas, el Cliend-Side Objet Model (CSOM) y la interfaz REST, que complementaban a los servicios Web de la plataforma, ofreciendo más posibilidades de desarrollo. Mientras que en el último SharePoint, la versión 2013, se han añadido nuevas funcionalidades al CSOM, así como una nueva y más limpia interfaz REST.
Dentro de las múltiples versiones del modelo de objetos de cliente de SharePoint 2013, nos encontramos con un nuevo SDK para el desarrollo de aplicaciones móviles, el Mobile Object Model.
=======
master Desde el Mobile Object Model, podemos trabajar con listas, bibliotecas de documentos, las nuevas notificaciones push (artículo de Adrián Díaz en CompartiMOSS) de SharePoint 2013, Perfiles de usuarios, Social, y casi todos los elementos que SharePoint expone en cliente.
Una nueva oportunidad para mejorar la movilidad de las empresas que usan SharePoint, ya que pueden extender sus procesos empresariales de forma universal a todos los usuarios, estén donde estén y tanto con un ordenador como con un móvil. Pensemos en aplicaciones que permitan aprobar flujos de trabajo en SharePoint, consultar datos de clientes en listas o almacenar fotos geo-localizadas en una biblioteca de documentos en SharePoint.
En este artículo, haremos una introducción a la versión de Windows Phone, dejando para el siguiente la versión REST, que nos permitiría hacer un cliente más universal para Windows 8, iPhone o Android.
El CSOM de Windows Phone usa el servicio WCF, client.svc, que es el encargado de analizar y ejecutar las consultas del cliente, usando el modelo de objetos de servidor, y devolver el resultado en JSON al cliente para que pueda trabajar con los objetos que necesite. Siguiendo el siguiente diagrama de arquitectura.
Si ya hemos trabajado con la implementación Silverlight del CSOM, trabajar con esta versión para Windows Phone es prácticamente lo mismo, básicamente hay que tener presente las llamadas asíncronas y que los objetos no se cargan hasta que ejecutemos la consulta en el servidor.
Autenticación
Hasta ahora, el principal problema que teníamos con Windows Phone y la integración con SharePoint es el de la autenticación del usuario frente a SharePoint. Para esto, tenemos una clase, Authenticator, que se encarga de realizar la autenticación por nosotros, aunque podemos realizarla manualmente.
var context = new ClientContext("https://xxx.sharepoint.com");
var authenticator = new Authenticator();
authenticator.CookieCachingEnabled = true;
context.Credentials = authenticator;
Consultas a lista
No tenemos cambios significativos cuando realizamos consultas a listas, básicamente obtenemos la lista, con o sin el CAML query, trabajando siempre desde el contexto de cliente y en el ExecuteQueryAsync obtenemos los elementos de esa lista o consulta.
1 var lista = new ObservableCollection<Announcement>();2<<<<<<< HEAD3 var query = GetAnnouncementQuery();4 var items = Context.Web.Lists.GetByTitle("Announcements").GetItems(query);5 Context.Load(items);6 Context.Load(items, listItems => listItems.Include(item => item.FieldValuesAsText));7 Context.ExecuteQueryAsync(8 delegate(object sender, ClientRequestSucceededEventArgs args)9 {10 foreach (var item in items)11 {12 var anuncio = new Announcement();13 anuncio.ID = item.Id.ToString();14 anuncio.Title = item.FieldValuesAsText["Title"];15 anuncio.Body = item.FieldValuesAsText["Body"];16 anuncio.Expires = item.FieldValuesAsText["Expires"];17 anuncio.Created = item.FieldValuesAsText["Created"];18 lista.Add(anuncio);19 }20 },21 delegate(object sender, ClientRequestFailedEventArgs args)22 {23 //Manejamos el error de la consulta24=======25
12
1 var query = GetAnnouncementQuery();2
1 var items = Context.Web.Lists.GetByTitle("Announcements").GetItems(query);2
1 Context.Load(items);2
1 Context.Load(items, listItems => listItems.Include(item => item.FieldValuesAsText));2
12
1 Context.ExecuteQueryAsync(2
1 delegate(object sender, ClientRequestSucceededEventArgs args)2
1 {2
1 foreach (var item in items)2
1 {2
1 var anuncio = new Announcement();2
1 anuncio.ID = item.Id.ToString();2
1 anuncio.Title = item.FieldValuesAsText["Title"];2
1 anuncio.Body = item.FieldValuesAsText["Body"];2
1 anuncio.Expires = item.FieldValuesAsText["Expires"];2
1 anuncio.Created = item.FieldValuesAsText["Created"];2
12
1 lista.Add(anuncio);2
1 }2
12
1 },2
1 delegate(object sender, ClientRequestFailedEventArgs args)2
1 {2
1 //Manejamos el error de la consulta2
1>>>>>>> master2 });3
Crear elementos en lista
Como siempre, nos creamos un objeto del tipo ListItemCreationInformation y lo envíanos al contexto.
1 var subscriptionList = Context.Web.Lists.GetByTitle("HubSubscribers");2<<<<<<< HEAD3 Context.Load(subscriptionList);4 deviceItem = subscriptionList.AddItem(new ListItemCreationInformation());5 deviceItem["Title"] = displayName;6 deviceItem["UserAccount"] = acccountName;7 deviceItem["ChannelUri"] = pushChannel;8 deviceItem["ChannelUriDate"] = System.DateTime.Now;9 deviceItem["DeviceId"] = deviceId;10 deviceItem.Update();11=======12
1 Context.Load(subscriptionList);2
1 deviceItem = subscriptionList.AddItem(new ListItemCreationInformation());2
1 deviceItem["Title"] = displayName;2
1 deviceItem["UserAccount"] = acccountName;2
1 deviceItem["ChannelUri"] = pushChannel;2
1 deviceItem["ChannelUriDate"] = System.DateTime.Now;2
1 deviceItem["DeviceId"] = deviceId;2
1 deviceItem.Update();2
1>>>>>>> master2 Context.ExecuteQuery();3
Obtener un perfil de usuario
En el CSOM de SharePoint 2013 tenemos acceso a los perfiles de usuario, y en Windows Phone también. Para esto, nos creamos un PeopleManager y obtenemos las propiedades que necesitemos.
1 var peopleManager = new PeopleManager(Context);2<<<<<<< HEAD3 var personProperties = peopleManager.GetPropertiesFor(userAccount);4 context.Load(personProperties, p => p.AccountName, p => p.DisplayName, p => p.Email, p => p.UserProfileProperties,5 p => p.DirectReports, p => p.Peers, p => p.PictureUrl);6 context.ExecuteQueryAsync(7 delegate(object sender1, ClientRequestSucceededEventArgs args)8 {9 var profile = new Profile();10 profile.AccountName = personProperties.AccountName;11 profile.DirectReports = personProperties.DirectReports.ToList();12 profile.Peers = personProperties.Peers.ToList();13 profile.DisplayName = personProperties.DisplayName;14 profile.PictureUrl = personProperties.PictureUrl;15 profile.Email = personProperties.Email;16 profile.Manager = personProperties.UserProfileProperties["Manager"];17 profile.Status = personProperties.UserProfileProperties["SPS-StatusNotes"];18 profile.WorkPhone = personProperties.UserProfileProperties["WorkPhone"];19 profile.Department = personProperties.UserProfileProperties["Department"];20 loadProfileCompletedCallback(new LoadProfileCompleteEventArgs { Profile = profile });21 },22 delegate(object sender1, ClientRequestFailedEventArgs args)23 {24 //Manejamos el error de la consulta25=======26
1 var personProperties = peopleManager.GetPropertiesFor(userAccount);2
12
1 context.Load(personProperties, p => p.AccountName, p => p.DisplayName, p => p.Email, p => p.UserProfileProperties,2
1 p => p.DirectReports, p => p.Peers, p => p.PictureUrl);2
1 context.ExecuteQueryAsync(2
1 delegate(object sender1, ClientRequestSucceededEventArgs args)2
1 {2
1 var profile = new Profile();2
1 profile.AccountName = personProperties.AccountName;2
1 profile.DirectReports = personProperties.DirectReports.ToList();2
1 profile.Peers = personProperties.Peers.ToList();2
1 profile.DisplayName = personProperties.DisplayName;2
1 profile.PictureUrl = personProperties.PictureUrl;2
1 profile.Email = personProperties.Email;2
1 profile.Manager = personProperties.UserProfileProperties["Manager"];2
1 profile.Status = personProperties.UserProfileProperties["SPS-StatusNotes"];2
1 profile.WorkPhone = personProperties.UserProfileProperties["WorkPhone"];2
1 profile.Department = personProperties.UserProfileProperties["Department"];2
12
1 loadProfileCompletedCallback(new LoadProfileCompleteEventArgs { Profile = profile });2
1 },2
1 delegate(object sender1, ClientRequestFailedEventArgs args)2
1 {2
1 //Manejamos el error de la consulta2
1>>>>>>> master2 });3
Conclusiones
¿A qué esperamos para desarrollar aplicaciones de negocio para Windows Phone? Personalmente, creo que nos puede abrir un nuevo abanico de posibilidades y de aplicaciones empresariales que no han terminado de llegar con SharePoint 2010. Por cierto, aunque no lo he probado al 100%, este modelo de objetos de cliente también funciona con SharePoint 2010, salvo las funcionalidades nuevas, como los perfiles, que no tenían soporte de cliente en SharePoint 2010.
<<<<<<< HEAD
Alberto Diaz Martin
MVP SharePoint
adiazcan@hotmail.com
@adiazcan
Alberto Diaz Martin MVP SharePoint adiazcan@hotmail.com @adiazcan http://geeks.ms/blogs/adiazmartin
master