Aplicando Silverlight a “la V de MVC”

En el último artículo que escribí, relacionado con la tecnología ASP.NET MVC, hablé de como explotar los datos de nuestra aplicación web mediante los RIA Services de Silverlight. Pero también comenté que se puede acceder a ellos sin necesidad de utilizar dichos servicios, que es lo que vamos a ver en este caso: el uso de Silverlight como plataforma para mejorar la interfaz de usuario, o lo que en ASP.NET MVC viene a ser la “la V (Vista) ”.

Inicialmente lo que hacemos es crear un proyecto de tipo Silverlight Application llamado SilverlightDep y que se alojará en una aplicación web ASP.NET MVC. Al igual que en el resto de aplicaciones ASP.NET MVC se nos preguntará si queremos crear un proyecto de pruebas unitarias a lo que diremos que no (de momento).

SilverApp image image

A continuación, añadimos la base de datos AdventureWorks_Data a nuestro proyecto, y tal y como hemos visto en otras ocasiones creamos un modelo de acceso a datos de tipo ADO.NET Entity Data Model que nos permita acceder a los elementos de la tabla Department.

image image  imageimage

Una vez definido nuestro modelo de datos, pasamos a diseñar el objeto Silverlight que se encargará de mostrar dichos datos de la forma deseada. Para ello abrimos el archivo Main.xaml, y añadimos un ListBox, llamado Departments, que se encargará de mostrar los nombres de los departamento, y un TextBlock, llamado DepartmentsInfo, en el cual se mostrará toda la información relacionada con el departamento seleccionado. Además configuramos el evento de carga de nuestro control de usuario para que se lance con la carga de la página “Page_Loaded”.

image 

Dentro del proyecto SilverlightDep, añadimos una clase llamada Department que nos permita trabajar con nuestros datos mediante dicho objeto. Por ello, este tiene que tener las mismas propiedades que la tabla Department de nuestra base de datos, para que sea posible el mapeo.

  1. public class Department
  2.     {
  3.  
  4.             public int DepartmentID { get; set; }
  5.             public string Name { get; set; }
  6.             public string GroupName { get; set; }
  7.             public DateTime ModifiedDate { get; set; }
  8.     }

Añadimos las siguientes referencias al proyecto SilverlightDep, para que podamos utilizar Json para serializar nuestros datos, y poder mostrarlos a través de nuestra vista:

System.Runtime.Serialization

System.ServiceModel.Web

Una vez que ya tenemos la interfaz diseñada, vamos a dotar a cada elemento de la funcionalidad específica. Para ello vamos al archivo Main.xaml.cs, añadimos la siguiente referencia:

Inicializamos un objeto de tipo lista de departamentos:

  1. IList<Department> result;

Y añadimos el siguiente código:

– Se lanza la aplicación cliente de Silverlight

  1. void Page_Loaded(object sender, RoutedEventArgs e)
  2.         {
  3.             WebClient wc = new WebClient();
  4.             wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
  5.             wc.OpenReadAsync(new Uri(«http://localhost:49705/Department/List»));
  6.         }

*Para saber cuál es la url que debemos indicar, es necesario compilar la aplicación y ver en que sitio web se está ejecutando. La ruta Department/List se define así porque vamos a trabajar con un controlador llamado Department, y una vista llamada List.

– Se leen los datos de nuestro objeto y se cargan en el ListBox, mediante el uso de la serialización en Json

  1. void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
  2.         {
  3.             DataContractJsonSerializer json = new DataContractJsonSerializer(typeof(List<Department>));
  4.             result = (List<Department>)(json.ReadObject(e.Result));
  5.             for (int i = 0; i < result.Count; i++)
  6.             {
  7.                 Departments.Items.Add(result[i].Name);
  8.             }
  9.  
  10.         }

– Se muestra en el TextBlock la información de cada elemento seleccionado en el ListBox

  1. private void Departments_SelectionChanged(object sender, SelectionChangedEventArgs e)
  2.         {
  3.  
  4.             int index = Departments.SelectedIndex;
  5.             DepartmentsInfo.Text = «DepartmentID: « + result[index].DepartmentID.ToString() + «n» +
  6.                               «Name: « + result[index].Name.ToString() + «n» +
  7.                               «GroupName: « + result[index].GroupName.ToString() + «n» +
  8.                               «ModifiedDate: « + result[index].ModifiedDate.ToString();
  9.         }

Por último tenemos que crear la vista específica que nos permita interactuar con nuestro objeto cliente Silverlight. Para ello creamos un controlador llamado Department, y que contendrá un ActionResult, que nos devuelva a través de Json la vista que nosotros queremos. Para ello dentro de SilverlightDep.Web, hacemos clic con el botón derecho sobre Controllers > AddController, y creamos un controlador que llamaremos DepartmentController.

Dentro de este archivo:

– Hacemos referencia a las siguientes bibliotecas:

  1. using SilverMvcApp.Web.Models;

– Instanciamos la entidad con la que vamos a trabajar:

  1. AdventureWorks_DataEntities entity = new AdventureWorks_DataEntities();

– Creamos un resultado de acción que nos muestre los datos definidos en la entidad, en forma de lista

  1. public ActionResult List()
  2.         {
  3.             return Json(entity.Department.ToList(),JsonRequestBehavior.AllowGet);
  4.         }

Es necesario, indicar la opción JsonRequestBehavior.AllowGet, ya que si no, podemos tener problemas de acceso a las peticiones Json.

Por último creamos la vista correspondiente, para ello hacemos clic con el botón derecho sobre List > AddView.

image

Dentro de la vista List, en el apartado en MainContent, añadimos nuestro objeto Silverlight, cuyo código generado podemos encontrar en la página de prueba SilverlightDepTestPage.aspx

  1.     <div id=»silverlightControlHost»>
  2.         <object data=»data:application/x-silverlight-2,» type=»application/x-silverlight-2″ width=»100%» height=»100%»>
  3.           <param name=»source» value=»ClientBin/SilverlightDep.xap»/>
  4.           <param name=»onError» value=»onSilverlightError» />
  5.           <param name=»background» value=»white» />
  6.           <param name=»minRuntimeVersion» value=»4.0.50401.0″ />
  7.           <param name=»autoUpgrade» value=»true» />
  8.           <a href=»http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0″ styletext-decoration:none»>
  9.               <img src=»http://go.microsoft.com/fwlink/?LinkId=161376″ alt=»Get Microsoft Silverlight» styleborder-style:none»/>
  10.           </a>
  11.         </object><iframe id=»_sl_historyFrame» stylevisibility:hidden;height:0px;width:0px;border:0px»></iframe></div>

Compilamos (F5), y el resultado que obtendríamos sería el siguiente.

image 

Si queremos utilizar este objeto en cualquier otra vista, lo único que tenemos que hacer es insertar este mismo código en la vista específica.

Además vamos a ver este mismo proceso pero utilizando un modelo de datos LinqToSql, ya que en artículos anteriores así me lo pedíais. La mayoría del procedimiento es similar a lo visto anteriormente, por lo que sólo comentaré las cosas diferentes. En este caso, nuestro modelo de acceso a datos será de tipo LINQ to SQL Classes, y lo llamaremos DepartmentModel.

image

Y una vez creado el modelo, debemos modificar el archivo DepartmentController, y configurar nuestro resultado de acción List de la siguiente forma:

  1. public ActionResult List()
  2.         {
  3.             DepartmentModelDataContext db = new DepartmentModelDataContext();
  4.             var deps = from dep in db.Departments
  5.                        select new
  6.                        {
  7.                            dep.DepartmentID,
  8.                            dep.Name,
  9.                            dep.GroupName,
  10.                            dep.ModifiedDate
  11.  
  12.                        };
  13.             return Json(deps,JsonRequestBehavior.AllowGet);
  14.  
  15.         }

De esta forma, combinando ASP.NET MVC y Silverlight, podemos crear aplicaciones muy potentes a nivel de interfaz de usuario…¡¡entre otras cosas!!

Proteger/Desproteger múltiples documentos en WSS 3.0

Este artículo viene a responder una pregunta realizada a través del blog a cerca de cómo proteger múltiples documentos a la vez en WSS 3.0 una vez que estos ya están almacenados en nuestra biblioteca de documentos.

Generalmente cuando subimos documentos mediante carga múltiple, estos se quedan desprotegidos, por lo que es necesario ir protegiéndolos uno a uno posteriormente. 

image imageimage

Pero esto se puede evitar de manera sencilla si utilizamos  SharePoint Designer 2007. Para ello abrimos nuestro sitio con SharePoint Designer y navegamos hasta la biblioteca de documentos en cuestión (sabemos que los documentos están desprotegidos porque aparece una flecha verde a mano izquierda de cada uno de ellos). A continuación seleccionamos todos los documentos que queremos proteger, y hacemos clic con el botón derecho sobre la opción Check In (Proteger), de forma que nos aparece una pantalla en la que podemos introducir comentarios en el versionado de los documentos. De esta forma tan sencilla conseguimos agilizar muchísimo un proceso que, hecho desde nuestro sitio SharePoint, sería muy tedioso.

image imageimage

El proceso para desproteger múltiples documentos a la vez, se realizaría de forma similar pero esta vez seleccionando la opción Check Out (Desproteger).

*En MOSS, aunque se podría utilizar este “truco”, también existe una opción para realizar la protección múltiple de documentos desde el propio sitio de SharePoint. Para ello es necesario ir a Site Actions > Manage content and structure (Acciones del sitio > Administrar contenido y estructura) y navegar hasta nuestra biblioteca. Seleccionamos todos los documentos y dentro del menú Actions (Acciones) seleccionamos Check In (Proteger).

image 

Y esto es todo, un pequeño aporte que espero os sea de utilidad!!!

Integración de Silverlight + RIA Services con ASP.NET MVC

Antes de irme de vacaciones, he estado peleándome unos días para integrar una aplicación Silverlight 4.0 dentro de un sitio web ASP.NET MVC, y por fin lo he conseguido. Aunque este no es el caso del que voy a hablar hoy, ya que después de lograr que funcionara decidí probar como sería realizar el mismo proceso pero con RIA Services, y la verdad es que facilita bastante el trabajo. Por lo que es de este último caso del que voy a hablar hoy.

Antes de empezar a trabajar con nuestra aplicación es necesario que instalemos el SDK de Silverlight 4.0WCF RIA Services V1.0 for Silverlight 4 and Visual Studio 2010. Una vez instalados estos plugins, abrimos Visual Studio y creamos un proyecto de tipo Silverlight Application al que llamaremos RiaApp. Si vamos siguiendo el wizard de creación, vemos que en la primera pantalla nos pregunta en que tipo de proyecto web vamos a alojar la aplicación, donde debemos indicar ASP.NET MVC Web Project. En la parte de abajo de dicha pantalla indicamos que la versión de Silverlight que vamos a utilizar es la 4.0.  y además activamos la casilla que habilita los servicios RIA para que podamos trabajar con ellos. Por último al alojar nuestro proyecto en una aplicación ASP.NET MVC nos pregunta si queremos crea un proyecto de pruebas unitarias a lo que diremos que no

 image image image

De forma que se crea la estructura específica de nuestra aplicación tal y como podemos observar a continuación en la siguiente imagen:

image

Siguiendo con el procedimiento normal de una aplicación ASP.NET MVC lo primero que hacemos es crear nuestro modelo de objeto, para lo cual es necesario añadir la fuente de datos de la cual extraeremos la información. Para ello hacemos clic con el botón derecho sobre App_Data > Add > Existing item, y seleccionamos la base de datos AdventureWorks_Data. A continuación vamos a definir el modelo que nos permita trabajar con la base de datos, para ello dentro de la carpeta Models hacemos clic con el botón derecho Add> New Item> ADO.NET Entity Data Model y vamos siguiendo el Wizard hasta llegar al punto en el que tenemos que seleccionar la tabla o tablas que queremos agregar y que en nuestro caso será Product

image imageimage image

Por último depuramos(F6) la aplicación para que se actualicen todas las modificaciones y podamos utilizar la base de datos.

El siguiente paso que vamos a dar es la creación de un servicio de dominio para que podamos conectar con nuestro objeto de datos, desde el cliente. Para ello hacemos clic con el botón derecho sobre el proyecto web Add>New Item> Domain Service y le damos el nombre de  AdventureService. A continuación nos aparece una pantalla para seleccionar el contexto de objeto con el que vamos a trabajar que en nuestro caso es la tabla Product, y para la cual activaremos la opción de editar, de forma que podamos modificar los valores de la misma, y la de generación de metadatos, de forma que podamos validarlos.

image image

Por último lo que vamos a hacer es añadir nuestra tabla a la aplicación Silverlight en forma de DataGrid. Para ello, si hacemos clic en la pestaña de Data Sources , cuando estamos en la aplicación Silverlight, nos aparece el contexto de datos que hemos creado. De forma que si expandimos Product y arrastramos el modelo en forma de Datagrid a la página MainPage.xaml este se genera de forma automática

image image

Tras realizar algunas modificaciones sobre el DataGrid para que sólo se muestren algunos de los campos de la lista, compilamos(F5) nuestra aplicación y vemos que se abre la página RiaAppTestPage.aspx donde aparecen nuestros datos:

image

Por último lo que vamos a hacer es integrar el objeto Silverlight creado dentro de nuestra página principal. Para ello abrimos la vista Index del controlador Home que se encuentra en Views >Home, y añadimos el código que se genera al crear nuestra aplicación, que se encuentra dentro de la página RiaAppTestPage.aspx:

  1. <object data=»data:application/x-silverlight-2,» type=»application/x-silverlight-2″ width=»100%» height=»100%»>
  2.           <param name=»source» value=»ClientBin/RiaApp.xap»/>
  3.           <param name=»onError» value=»onSilverlightError» />
  4.           <param name=»background» value=»white» />
  5.           <param name=»minRuntimeVersion» value=»4.0.50401.0″ />
  6.           <param name=»autoUpgrade» value=»true» />
  7.           <a href=»http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50401.0″ styletext-decoration:none»>
  8.               <img src=»http://go.microsoft.com/fwlink/?LinkId=161376″ alt=»Get Microsoft Silverlight» styleborder-style:none»/>
  9.           </a>
  10.         </object>

Y el resultado final sería el siguiente, donde gracias a Silverlight 4.0 podemos mostrar e interactuar con los distintos elementos del DataGrid desde nuestra aplicación ASP.NET MVC, y lo mejor de todo sin escribir nada de código:

image 

¡¡¡Fácil, sencillo y para toda la familia!!!

Aquí dejo el código para su descarga, teniendo en cuenta que hay que añadir la base de datos AdventureWorks_Data para que funcione correctamente.

ASP.NET MVC 3 Preview 1

Scott Gu publico ayer en su blog un post en el que habla sobre algunas de las novedades que introduce la nueva versión de ASP.NET MVC, y cuya preview1 ya podemos descargar aquí.

El post es bastante completo ya que detalla las mejoras agrupadas por secciones por lo que recomiendo su lectura sin duda alguna. A continuación os dejo con una pequeña reseña de lo que comenta Scott a modo de resumen:

  • Mejoras a nivel de vistas
    • Dialogo de motor de vista (View Engine). Permite elegir la sintaxis con la que queremos trabajar para crear nuestras vistas.

 

image

  • Mejoras a nivel de controlador
    • Filtros globales. Se pueden aplicar filtros globales a todos los controladores de una aplicación
    • Nueva propiedad dinámica de modelo de vista(ViewModel). Viene a realizar la misma labor que ViewData. Permite pasar los datos de un modelo a una vista pero de forma dinámica.
    • Nuevos tipos de resultados de acciones(ActionResult):
      • HttpNotFoundResult: se usa para indicar que el recurso requerido por la petición web no se encuentra
      • PermanentRedirects: se usa para indicar una redirección permanente
      • HttpStatusCodeResult: se utiliza para establecer una respuesta específica de estado de código y descripción
  • Mejoras a nivel de Modelo
    • Validación(soporte de propiedades del Framework 4.0):
      • Soporte de los atributos de metadatos de DataAnnotations
      • Soporte de la interfaz IValidatableObject
  • Mejoras de JavaScript y AJAX
    • Soporte a Json binding
  • Mejoras en la inyección de dependencias (DI)
    • Soporte de las siguientes dependencias:
      • Controllers (registering & injecting controller factories, injecting controllers)
      • Views (registering & injecting view engines, injecting dependencies into view pages)
      • Action Filters (locating & injecting filters)
    • Se esta trabajando para que en versiones futuras se puedan añadir soporte a las siguientes dependencias
      • Model Binders (registering & injecting)
      • Value Providers (registering & injecting)
      • Validation Providers (registering & injecting)
      • Model metadata Providers (registering & injecting)

Podéis encontrar el post completo de Scott aquí:

http://weblogs.asp.net/scottgu/archive/2010/07/27/introducing-asp-net-mvc-3-preview-1.aspx

[ASP.NET MVC] ActionResult personalizado para la descargar de documentos

Ya de vuelta al mundo ASP.NET MVC, y antes del parón vacacional, vamos a ver una pequeña aplicación para cargar y descargar documentos de nuestra web.

En primer lugar, implementaremos el método de carga. Nuestra proyecto nos debe permitir cargar documentos dentro del sitio web, de forma que estos puedan ser descargados posteriormente por cualquier usuario. ASP.NET MVC soporta la carga de archivos, pero para ello son necesarios dos componentes:

  • un formulario cuyo atributo enctype tenga el valor "multipart/form-data" y contenga una etiqueta de tipo <input type="file"…>
  • una acción del controlador que reciba la información de la carga y la ejecute.

Para ello tras crear nuestro proyecto de tipo ASP.NET MVC 2 Web Application, que llamaremos ManageFiles:

image image

Añadimos un controlador que llamaremos ManageController, y que se encargará de gestionar tanto la carga como la descarga de los documentos:

image

Dentro de este:

  1. Añadimos la referencia
    1. using System.IO;

        de forma que podamos utilizar operaciones de tipo Entrada/Salida con los documentos.

  2. Creamos un ActionResult llamado Upload, que se encargará de cargar el archivo seleccionado en nuestra carpeta Content, y que tendrá el siguiente código:
  1. public ActionResult Upload(HttpPostedFileBase file)
  2.         {
  3.             var fileName = Path.GetFileName(file.FileName);//obtenemos el nombre del archivo a cargar
  4.             file.SaveAs(Server.MapPath(@"~\Content\" + fileName));//guardamos el archivo en la ruta física que corresponde a la ruta virtual del archivo
  5.             return RedirectToAction("Index");//volvemos a la página principal
  6.         }

* Para cargar un archivo en una ruta específica del servidor es necesario usar la clase HttpPostedFileBase

A continuación, abrimos la vista Index que se crea por defecto y dentro del apartado de contenido principal, añadimos el siguiente código que se encargará de mostrarnos el formulario que nos permite navegar por los archivos de nuestro equipo, y que ejecuta la acción de Upload:

  1. <form action="/Manage/Upload" method="post" enctype="multipart/form-data"/>
  2.     <label>Filename:<input type ="file" name="file"/></label>
  3.     <input type="submit" value="Guardar"/>

Para que podamos acceder de forma sencilla a este área de la aplicación, añadimos una nueva pestaña dentro del menú de la página maestra que se encuentra dentro de la carpeta ViewsShared, mediante el siguiente código:

  1. <li><%: Html.ActionLink("Gestión Documental", "Index", "Manage")%></li>

Si ejecutamos la aplicación y accedemos a la sección Gestión Documental, al pulsar al botón Examinar ya podemos navegar por los documentos de nuestro equipo sin problema, y una vez que pulsamos al botón Guardar podemos ver como el archivo examinado se guarda en la ruta indicada:

image image image

Por otro lado, después de ver el proceso de carga, el cual la mayoría ya habrá implementado de una forma u otra, llegamos a la parte que da título al articulo, el proceso de descarga. Este viene a complementar la carga de archivos con la posibilidad de poder abrir o descargar archivos almacenados en el servidor. Para ello es necesario implementar una clase personalizada que herede de ActionResult, y a la cual llamaremos GetFile

Hacemos clic con el botón derecho sobre nuestro proyecto y seleccionamos Add >Class 

image image

En dicha clase:

  1. Añadimos la referencia
    1. using System.Web.Mvc;

  2. Configuramos nuestra clase para que herede de ActionResult
  3. Inicializamos los parámetros que necesitamos para poder acceder a nuestros archivos, y que son el nombre y la ruta de los mismos:
  1. public string FileName { get; set; }
  2.         public string Path { get; set; }

    4. Y sobrescribimos el método ExecuteResult, que se encargará de implementar la ventana de descarga ( “content-disposition” ) utilizando el siguiente código:

 

  1. public override void ExecuteResult(ControllerContext context)
  2.         {
  3.             context.HttpContext.Response.Buffer = true;
  4.             context.HttpContext.Response.Clear();
  5.             context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + FileName);
  6.             context.HttpContext.Response.WriteFile(context.HttpContext.Server.MapPath(Path));
  7.         }

A continuación vamos al controlador ManagerController, y añadimos el código, que nos permita descargar el archivo Objetivo.docx, que hemos subido anteriormente a nuestra carpeta Content mediante el proceso de carga :

  1. public GetFile DownloadFile()
  2.         {
  3.  
  4.             return new GetFile
  5.             {
  6.                 
  7.                 FileName = "Objetivo.docx",
  8.                 Path = @"~/Content/Objetivo.docx"
  9.  
  10.             };
  11.         }

Por último añadimos, dentro de la vista Index, un Html.ActionLink que ejecute la acción de descarga:

  1. <%: Html.ActionLink("Descarga de documentos", "DownloadFile", "Manage")%>

Al ejecutar la aplicación, y seleccionar la opción Descarga de documentos vemos que aparece la siguiente pantalla:

image 

Esta sería la forma más básica de implementar la descarga, pero vemos que esta opción no es muy flexible ya que tenemos que indicar el nombre de un archivo en concreto a través del código para poder realizar la descargar, cuando lo ideal seria poder seleccionar el archivo dinámicamente. Por ello en el próximo artículo veremos como mejorar esto para que podamos seleccionar el archivo que nosotros queramos y descargarlo, todo ello a través de la interfaz de usuario.

ECMAScript Client Object Model SharePoint 2010

Después de un pequeño parón en mi blog, debido a los Sanfermines, y ya para terminar con la serie de artículos relacionados con el modelo de objetos cliente de SharePoint 2010, hoy vamos a ver el último tipo de cliente con el que podemos trabajar y que se trata de ECMAScript.

Para ello abrimos Visual Studio 2010, y creamos un nuevo proyecto de tipo New Project > Sharepoint2010 > VisualWebPart, indicando el sitio sobre el que vamos a implementar nuestra aplicación http://sharepoint2010:200 y el alcance de la misma, que en este caso será a nivel de granja de servidores. Es necesario tener en cuenta que para que podamos ejecutar nuestra aplicación correctamente a este nivel, debemos contar con permisos de administrador.

image image

Esta implementación del cliente se puede realizar de dos formas: añadiendo nuestro código a un archivo y llamándolo desde nuestro control .ascx, o integrando el propio código dentro del control de usuario. En nuestro caso vamos a hacer la implementación más sencilla, y el código se lanzara al acceder a la página en la que insertemos nuestra web part ya que lo que pretendemos es ver el funcionamiento del mismo. Pero esta bien saber que esta misma aplicación se puede implementar de forma más “elegante” si por ejemplo, lanzamos nuestro código Javascript desde un botón.

A continuación es necesario añadir el siguiente código dentro del archivo VisualWebPart1UserControl.ascx:

  1. <SharePoint:ScriptLink ID="ScriptLink" Name="SP.js" runat="server" OnDemand="true" Localizable="false"></SharePoint:ScriptLink>

Esto nos permite trabajar con el modelo de objeto JavaScript que viene definido en el archivo sp.js. Este archivo al igual que el encargado de la lógica de transporte necesaria para procesar peticiones al servidor (spruntime.js) se encuentran dentro de la carpeta LAYOUTS dentro de la ruta de definición de los sitios SharePoint 2010.

Una vez establecida la referencia al archivo de definición del modelo de objeto, añadimos el código de nuestra función que en este caso se encargará de crear un sitio, como vimos en el cliente .NET, con las siguientes características:

  1. <script type="text/javascript">
  2.         var clientContext = null;
  3.         var web = null;
  4.         ExecuteOrDelayUntilScriptLoaded(Initialize, "sp.js");
  5.         function Initialize() {
  6.             clientContext = new SP.ClientContext.get_current();
  7.             web = clientContext.get_web();
  8.             var webCreateInfo = new SP.WebCreationInformation();
  9.             webCreateInfo.set_description("Este es mi blog personal");
  10.             webCreateInfo.set_title("Blog personal de Goretti");
  11.             webCreateInfo.set_url("BlogPersonal");
  12.             webCreateInfo.set_useSamePermissionsAsParentSite(true);
  13.             webCreateInfo.set_webTemplate("BLOG#0");
  14.  
  15.             this.oNewWebsite = this.web.get_webs().add(webCreateInfo);
  16.  
  17.             clientContext.load(this.oNewWebsite, 'ServerRelativeUrl', 'Created');
  18.  
  19.             clientContext.executeQueryAsync(Function.createDelegate(this, this.onCreateWebSuccess),
  20.  
  21. Function.createDelegate(this, this.onQueryFailed));
  22.         }
  23.         function onCreateWebSuccess(sender, args) {
  24.             alert("Web site url : " + this.oNewWebsite.get_serverRelativeUrl());
  25.         }
  26.  
  27.         function onQueryFailed(sender, args) {
  28.             alert('request failed ' + args.get_message() + '\n' + args.get_stackTrace());
  29.         }
  30.     </script>​

Como podemos ver, la estructura de implementación del modelo es similar a la que utilizamos en cualquiera de los otros dos clientes.

1. Definimos el contexto de nuestro cliente

2. Definimos que es lo queremos cargar cuando se ejecute la query (clientContext.Load)

3. Ejecutamos la query (clientContext.executeQueryAsunc), que se encarga de mirar que es lo que esta definido en el método de carga  y en función de ello establecer la comunicación entre cliente y servidor para obtener los objetos con los que queremos trabajar

*Además, en este cliente en particular, hay que tener en cuenta que es necesario lanzar el método ExecuteOrDelayUntilScriptLoaded(Initialize, "sp.js"). Este se encarga de que el código JavaScript se ejecute después de que finalice la carga del código sp.js. Si no es así nuestra función no se ejecutará correctamente

Por último una vez compilada nuestra aplicación (F5), añadimos la web part implementada en el sitio donde queremos que esta se ejecute.

image 

De forma que en el momento que accedamos a la página que contenga dicha web part se ejecute nuestro código. Si el sitio con los parámetros que nosotros indicamos ya esta creado, nos salta la siguiente alerta, tal y como lo hemos definido:

image

Sin embargo, si no esta creado, dicho sitio se creará y nos aparecerá la siguiente alerta indicándonoslo, de esta forma ya podremos acceder a nuestro blog:

image image

Esta es sólo una de las muchas funciones que se pueden implementar desde un cliente JavaScript. Aquí os dejo otras funciones relacionadas como: borrar un sitio, borrar una lista, actualizar elemento de una lista…and ¡¡so on!!, para que probeis

Como ya hemos comentado antes esta aplicación se podría implementar de manera más “elegante”, pero esa parte la dejamos para más adelante. Así, con este artículo termino la serie de posts relacionados con el Modelo de Objeto Cliente en SP2010, y vuelvo al mundo ASP.NET MVC, que últimamente lo tengo un poco abandonado. ¡¡Será el verano!!

Mostrar pestaña programador en Office 2010

Para poder crear aplicaciones de tipo Office Business Application (OBA) con Office 2010, una de las opciones que se emplea es la personalización de nuestros documentos desde el propio Office gracias a la ayuda de la pestaña Programador. Esta nos permite crear documentos inteligentes basados en smart tags, que no son otra cosa que controles de formulario. Pero ¿que ocurre cuando esta pestaña no esta visible?(que por defecto no lo está), lo primero que piensas es ¿como lo hacía en 2007?, ya que a nivel de interfaz de usuario Office 2007 y 2010 no son tan diferentes.

En Office 2007 el proceso era el siguiente:

1. Hacíamos clic en el botón de Office ubicado en el extremo superior izquierdo

2. Hacíamos clic en el botón "Opciones de Excel"

3. En la opción "Más frecuentes", activábamos la opción "Mostrar ficha Programador en la cinta de opciones"

 tabprogrammostrarprog

Sin embargo cuando vamos a seguir los mismos pasos “more or less”, en 2010, no encontramos lo mismo.

1. Hacemos clic en el botón de Archivo ubicado en el extremo superior izquierdo, que es lo más parecido que tenemos al botón de Office en 2007

2. Hacemos clic en la sección "Opciones”, que también es lo más parecido a lo que teníamos en la versión anterior. Pero una vez se nos abre la ventana de opciones, vemos que en esta versión no existe la sección "Más frecuentes", y si miramos en la sección general no aparecen nada similar…ni en opciones avanzadas.

3. Tenemos que acceder a la sección Personalizar cinta de opciones para poder activar dicha funcionalidad, ya que si nos fijamos por defecto esta está sin activar.

image image

Una tontería..pero que muchas veces nos hace perder el tiempo innecesariamente (a mi me lo ha hecho perder!!!).

Además os dejo un link bastante interesante que estoy siguiendo para la personalización del backstage de Office 2010 ya que de momento no se está desarrollando mucho en esta línea.

Material evento “SharePoint 2010: Evolución vs Revolución”

Desde aquí me gustaría agradecer su asistencia a todas aquellas personas que se animaron a participar en la Jornada “SharePoint 2010: Evolución vs Revolución” que tuvo lugar ayer en los Centros de Excelencia Software de Navarra. En ella se pudieron ver las principales novedades y características que introduce la plataforma SharePoint 2010 con respecto a versiones anteriores , y algunos de los aspectos que contribuyen a dicha Evolución.

Como sería difícil resumir todo lo que se vio en esta charla en un post, me quedo con una frase que dijo Juan Carlos González: “SharePoint 2010 no se trata de un producto, sino de una plataforma que nos permite combinar diversas soluciones”.  Por lo tanto, debemos ser conscientes de que SharePoint se trata de un “mundo por explorar” con el que podemos trabajar para personalizar nuestras aplicaciones de forma que estas sean todo lo potentes y eficientes que estamos buscando.

Aquí os dejo la parte de la presentación que realizamos mi compañero Raúl y yo, referente al modelo de objeto en cliente, una de las principales mejoras a nivel de desarrollo de SharePoint 2010, y las demos que realizamos para cada uno de los clientes que se pueden implementar mediante este modelo de objeto : . NETThank-you-2, Silverlight, ECMAScript

Mostrar elementos de una lista en SharePoint 2010 mediante el modelo de objetos cliente Silverlight

Como ya vimos en el articulo anterior, el modelo de objetos cliente de SharePoint 2010 nos permite trabajar con tres tipos de clientes diferentes.

– Aplicaciones .NET

– Aplicaciones Silverlight

– Aplicaciones ECMAScript

Tras ver el ejemplo de un cliente .NET, en el artículo de hoy vamos a ver el siguiente tipo de aplicaciones con las que se puede trabajar, más en concreto vamos a ver como crear un elemento web de tipo Silverlight que nos permita navegar por los elementos de nuestra lista de Contactos mostrándonos toda la información de los mismos, ya que hasta ahora lo que se ve en la mayoría de Posts es como acceder a las distintas listas y sus propiedades pero no a sus elementos. Para ello vamos a ver los pasos que hemos seguido para la creación de nuestra Web Part y para la integración de la misma en SharePoint. De forma que el resultado que hemos obtenido es el siguiente:

image

Para ello lo que hacemos es crear una solución que integre por un lado un proyecto de tipo Aplicación de Silverlight donde definiremos los controles que vamos a utilizar para mostrar los datos de nuestros contactos y que van a ser :

– Un listbox donde mostraremos el apellido del contacto, y que nos permitirá ir navegando por los distintos contactos

– Un conjunto de labels, donde cargaremos todos los valores correspondientes a cada contacto (Nombre, Apellido, Compañía, Email…)

– Un elemento de tipo Imagen, donde cargaremos la imagen de cada uno de los contactos.

Y por otro lado un tipo de proyecto SharePoint>2010>Empty SharePoint Project, que será el que se encargue de cargar nuestra aplicación Silverlight en SharePoint. Pero para que ambas aplicaciones se integren es necesario añadir también un proyecto de tipo SharePoint> 2010> Modulo que se encargará de incluir el archivo .xap de Silverlight en SharePoint 2010.

image 

Una vez creado este modulo, eliminamos el archivo Sample.txt que se genera por defecto. Hacemos clic con el botón derecho sobre el Modulo y establecemos la propiedad Project Output References, tal y como se observa en la siguiente imagen:

image image

Y modificamos el archivo Elements.xml, de forma que indicamos al módulo de carga cual es la url de nuestro archivo .xap  y donde se tiene que guarda este dentro de nuestro sitio SharePoint.

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  3.   <Module Name="ModuloCarga" Url="StoreSilverlight">
  4.   <File Path="ModuloCarga\ContactosCein.xap" Url="ContactosCein.xap" Type="GhostableInLibrary" />
  5. </Module>
  6. </Elements>

Por último vamos a comprobar que nuestra solución se carga correctamente en nuestro sitio. Para ello añadimos dentro de una página (la que queramos) un elemento web de tipo Silverlight, en el que indicaremos cual es el archivo .xap que queremos cargar. Para ello abrimos el panel de herramientas, y en la opción Configurar indicamos la url relativa a nuestro archivo:

image image

Una vez comprobado que nuestra solución Silverlight se ha implementado correctamente en nuestro sitio, pasamos a implementar la lógica de la misma.

1. Para poder trabajar con el modelo de objeto cliente de Silverlight es necesario añadir las siguientes bibliotecas a nuestro proyecto:

Microsoft.SharePoint.Client.Silverlight.dll, Microsoft.SharePoint.Client.Silverlight.Runtime.dll

*Estas se encuentran dentro de la carpeta C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14TEMPLATELAYOUTSClientBin.

2. Añadimos las referencias necesarias en nuestra clase MainApp

  1. using Microsoft.SharePoint.Client;
  2. using System.Windows.Media.Imaging;

3. Sincronizamos la aplicación Silverlight con el sitio SharePoint, para ello es  necesario añadir el siguiente código dentro del evento de arranque Application_Startup de la aplicación(App.xaml.cs)

  1. ApplicationContext.Init(e.InitParams, SynchronizationContext.Current);

3. Inicializamos las variables y objetos que vamos a utilizar:

  1.       private delegate void UpdateUI();
  2.       ListItemCollection collListItem;
  3.       List<Contacto> miscontactos = new List<Contacto>();
  4.  
  5.       Contacto contacto;

4. Llamamos a nuestro método de carga Cargarelementos() desde el constructor MainPage() . Este se encarga de crear el contexto cliente para inicializar los objetos con los que vamos a trabajar

  1. public void Cargarelementos()
  2.         {
  3.  
  4.             ClientContext clientContext = new ClientContext(http://sharepoint2010:200);
  5.             Web web = clientContext.Web;
  6.             List oList = web.Lists.GetByTitle("Contactos");
  7.  
  8.             CamlQuery Query = new CamlQuery();
  9.             collListItem = oList.GetItems(Query);
  10.             clientContext.Load(collListItem);
  11.             clientContext.ExecuteQueryAsync(OnSucceeded, OnFailure);
  12.  
  13.         }

Una de las principales diferencias que vemos con respecto al ejemplo del artículo anterior, es que en este caso la llamada al contexto se hace de forma asíncrona, teniendo en cuenta que para ello hay que especificar cuales son los eventos hay que ejecutar en caso de éxito o fracaso.

5. Definimos el método que se encarga de crear nuestros objetos de tipo Contacto a partir de los elementos de nuestra lista de Contactos (LoadListItems), y al que llamaremos en caso de éxito, desde nuestro evento OnSucceeded.

  1. private void LoadListItems()
  2.         {
  3.             listacontactos.Items.Clear();
  4.             foreach (ListItem oListItem in collListItem)
  5.             {
  6.                 FieldUrlValue pictureUrl = oListItem["Foto"] as FieldUrlValue;
  7.                 Uri uri = new Uri(pictureUrl.Url, UriKind.Absolute);
  8.                 contacto = new Contacto(oListItem["FirstName"].ToString(), oListItem["Title"].ToString(), oListItem["WorkCity"].ToString(), oListItem["WorkZip"].ToString(), oListItem["WorkCountry"].ToString(), oListItem["Email"].ToString(), oListItem["CellPhone"].ToString(), oListItem["Company"].ToString(), uri);
  9.                 miscontactos.Add(contacto);
  10.                 Item elemento = new Item(oListItem["Title"].ToString());
  11.                 listacontactos.Items.Add(elemento);
  12.  
  13.             }
  14.  
  15.         }

*Para ello hemos definido previamente dos clases que nos permitan:

-  Crear objetos de tipo Contacto con unas propiedades especificas.

  1. public class Contacto
  2.     {
  3.         public string Name;
  4.         public string LastName;
  5.         public string City;
  6.         public string ZipCode;
  7.         public string Country;
  8.         public string Email;
  9.         public string Telefono;
  10.         public string Compañia;
  11.         public Uri urifoto;
  12.         public Contacto(string name, string lastname, string city, string zipcode, string country, string email, string telefono, string compañia, Uri foto)
  13.         {
  14.             Name = name;
  15.             LastName = lastname;
  16.             City = city;
  17.             ZipCode = zipcode;
  18.             Country = country;
  19.             Email = email;
  20.             Telefono = telefono;
  21.             Compañia = compañia;
  22.             urifoto = foto;
  23.         }
  24.     }

– Crear Items, para añadir elementos a nuestro ListBox

  1. public class Item
  2.     {
  3.         public string Name;
  4.  
  5.         public Item(string name)
  6.         {
  7.             Name = name;
  8.  
  9.         }
  10.         public override string ToString()
  11.         {
  12.             // Genera el texto mostrado en el ComboBox
  13.             return Name;
  14.         }
  15.     }

6. Configuramos los eventos de éxito o fracaso (en nuestro caso sólo se ejecuta código en el primero de ellos). Plena confianza 😉

  1. private void OnSucceeded(object sender, ClientRequestSucceededEventArgs e)
  2.         {
  3.             UpdateUI updateUI = LoadListItems;
  4.             this.Dispatcher.BeginInvoke(updateUI);
  5.         
  6.         }

7. Y por último configuramos el evento _SelectionChanged de nuestro ListBox, para que al seleccionar en los distintos contactos se carguen las propiedades especificas en cada caso.

  1. private void listacontactos_SelectionChanged(object sender, SelectionChangedEventArgs e)
  2.         {
  3.  
  4.             int Indice = listacontactos.SelectedIndex;
  5.  
  6.             NombreCont.Content = "Nombre: " + miscontactos[Indice].Name;
  7.             ApellidoCont.Content = "Apellido: " + miscontactos[Indice].LastName;
  8.             COmpañiaCont.Content = "Compañia: " + miscontactos[Indice].Compañia;
  9.             EmailCont.Content = "Email: " + miscontactos[Indice].Email;
  10.             telefonoCont.Content = "Teléfono:" + miscontactos[Indice].Telefono;
  11.             BitmapImage bi = new BitmapImage(miscontactos[Indice].urifoto);
  12.             ImagenContacto.Source = bi;
  13.  
  14.         }

De forma que ya tenemos nuestra aplicación implementada y corriendo en nuestro sitio SharePoint, tal y como podemos ver en la imagen inicial.

Recordar que esto es sólo una pequeña parte de todo lo que se puede hacer combinando estas dos potentes plataformas, por lo que os animo a que creéis  vuestras propias aplicaciones y exploréis toda la potencia que estas ofrecen

Aquí os dejo todo el código completo, por si alguien lo quiere utilizar como referencia.

*(Habría que implementar los proyectos ContactosCein y ImplementarSilver en una solución única)

Crear sitio en SharePoint 2010 mediante el modelo de objeto cliente (Client Object Model)

Aprovechando que el próximo 15 de Junio, se va a celebrar en el CES Microsoft de Navarra un evento sobre SharePoint 2010, en el que participaré junto con mi compañero Raúl Mayo y Juan Carlos González (Ciin), he vuelto “a mis orígenes” vinculados al mundo SharePoint y he estado trabajando en pequeñas aplicaciones relacionadas con el modelo de objetos cliente. Esto me ha permitido conocer de primera mano toda la potencia que presenta esta nueva característica de SharePoint 2010.

A modo de introducción en el tema, vamos a ver que es el modelo de objetos cliente y que características presenta. El modelo de objetos cliente (Client Object Model) se trata de una interfaz de programación (SharePoint 2010) que se ejecuta en los equipos cliente y que permite trabajar con objetos SharePoint de manera remota. Para los que hayamos trabajado con versiones anteriores de SharePoint, esto es una gran ventaja ya que no es necesario tener instalado SharePoint en nuestras máquinas para poder desarrollar aplicaciones para nuestros sitios.

Este modelo presenta las siguientes características:

−El acceso al servidor es vía API

−No hay necesidad de recurrir a los servicios web que expone la plataforma ni de implementar servicios personalizados.

−Permite desarrollar a nivel de:

  • Colecciones de sitios, sitios, plantillas de sitio
  • Listas, elementos de lista, vistas y esquemas
  • Archivos y carpetas
  • Elementos web
  • Seguridad
  • Tipos de contenido

Además, como podemos observar en la siguiente imagen existen tres tipos de clientes con los que se puede trabajar con este modelo de objeto:

 image

1. Cliente .NET

En este caso para poder escribir código del lado cliente, debemos utilizar las bibliotecas de SharePoint que tienen todos los métodos y clases necesarias para comunicarse con el servidor. Microsoft SharePoint 2010 nos proporciona estas dll que se encuentran localizadas en ISAPI y que son:

Microsoft.SharePoint.Client .dll: modelo de objeto en sí mismo

Microsoft.SharePoint.Client.Runtime.dll: lógica de transporte necesaria para procesar las peticiones al servidor

Las comunicaciones entre cliente y el servidor son síncronas.

2. Cliente Silverlight (3.0 o superiores)

En este cliente, al igual que en el anterior, son necesarias una serie de bibliotecas específicas para poder  ejecutar código cliente. Estas están localizadas en TEMPLATELAYOUTSClientBin y son:

Microsoft.SharePoint.Client.Silverlight.dll: modelo de objeto en sí mismo

Microsoft.SharePoint.Client.Silverlight.Runtime.dll: lógica de transporte necesaria para procesar las peticiones al servidor

Al contrario que en el caso anterior, las comunicaciones con el servidor son asíncronas. 

3. Cliente ECMAScript, que se ejecuta en el navegador. Para poder interactuar con él es necesario utilizar:

SP.js: modelo de objeto en sí mismo

SP.Runtime.js: lógica de transporte necesaria para procesar las peticiones al servidor

*Ambos archivos se encuentran localizadas en /LAYOUTS

Las comunicaciones con el servidor son asíncronas, los cambios del servidor no se reflejan automáticamente.

Además también tenemos que tener en cuenta la sintaxis de los objetos SharePoint. Como podemos ver en el siguiente cuadro, esta es diferente si trabajamos con objetos a nivel del servidor o a nivel de modelo objeto cliente.

Servidor

Client MO

SPContext

ClientContext

SPSite

Site

SPWeb

Web

SPList

List

SPListItem

ListItem

SPField

Field

Para entender todo esto un poco mejor vamos a ver un ejemplo del primero tipo de cliente. Para ello vamos a crear una aplicación que nos permita crear programáticamente un sitio SharePoint 2010 mediante el modelo de objetos cliente especifico.

Los pasos que seguimos para ello son:

1. Creamos un proyecto de tipo Consola de aplicación y añadimos las siguientes referencias:

  • Microsoft.SharePoint.Client
  • Microsoft.SharePoint.Client.Runtime

*Estas se encuentran dentro de la ruta C:Program FilesCommon FilesMicrosoft SharedWeb Server Extensions14ISAPI

2. Añadimos el espacio de nombres Microsoft.SharePoint.Client a nuestra clase Program.cs

  1. using Microsoft.SharePoint.Client;

3. Creamos un método llamado CreateSite, y dentro de él:

3.1 Creamos el contexto de nuestro cliente:

  1. ClientContext clientContext = new ClientContext(«http://sharepoint2010:200»);//Creamos contexto del cliente

3.2 Creamos el objeto cliente con una serie de parámetros:

  1. Web oWebsite = clientContext.Web;//Creamos un nuevo sitio dentro del contexto del cliente
  2.             WebCreationInformation webCreateInfo = new WebCreationInformation();//definimos información de creación de sitio
  3.             webCreateInfo.Title = «Sitio Prueba»;//Nombre sitio
  4.             webCreateInfo.Description = «Sitio de equipo»;//Decripción sitio
  5.             webCreateInfo.Url = «SitioPrueba»;//URL sitio
  6.             webCreateInfo.UseSamePermissionsAsParentSite = true;//Permisos sitio
  7.             webCreateInfo.WebTemplate = «STS#0 «;//Tipo de plantilla sitio -> Más información http://www.sharepointdevwiki.com/display/sp2010/Site+Templates+in+SharePoint+2010
  8.             Web oNewWebsite = oWebsite.Webs.Add(webCreateInfo);//Aplicamos los parámetros definidos a nuestro sitio del contexto cliente.

3.3 Creamos la consulta

  1. clientContext.Load(
  2.                 oNewWebsite,
  3.                 website => website.ServerRelativeUrl,
  4.                 website => website.Created);

Como se puede ver, aquí lo que hacemos es cargar el objeto SharePoint oNewWebSite con sus propiedades, e indicamos como parámetros de consulta el valor de la url relativa de nuestro sitio, y la fecha de creación que es lo que mostraremos por consola. 

3.4 Ejecutamos la consulta

  1. clientContext.ExecuteQuery();

Para optimizar la recuperación de datos, el modelo de objetos cliente va poniendo los objetos en cola hasta que no se hace una llamada a ExecuteQuery(). De forma que no hay ningún dato del servidor disponible hasta que no se invoca dicho método. *El método ExecuteQuery() es síncrono.

3.5 Mostramos la información de nuestro sitio por consola

  1. Console.WriteLine(«Server-relative Url: {0} Created: {1}», oNewWebsite.ServerRelativeUrl, oNewWebsite.Created);//Mostramos por consola la información de nuestro sitio
  2.             Console.ReadLine();

 

En resumen, el código completo que hemos utilizado para crear nuestro sitio es:

 

  1. class Program
  2.     {
  3.         static void Main(string[] args)
  4.         {
  5.             CreateSite();
  6.         }
  7.  
  8.         private static void CreateSite()
  9.         {
  10.             ClientContext clientContext = new ClientContext(«http://sharepoint2010:200»);//Creamos contexto del cliente
  11.             Web oWebsite = clientContext.Web;//Creamos un nuevo sitio dentro del contexto del cliente
  12.  
  13.             WebCreationInformation webCreateInfo = new WebCreationInformation();//definimos información de creación de sitio
  14.             webCreateInfo.Title = «Sitio Prueba»;//Nombre sitio
  15.             webCreateInfo.Description = «Sitio de equipo»;//Decripción sitio
  16.             webCreateInfo.Url = «SitioPrueba»;//URL sitio
  17.             webCreateInfo.UseSamePermissionsAsParentSite = true;//Permisos sitio
  18.             webCreateInfo.WebTemplate = «STS#0 «;//Tipo de plantilla sitio -> Más información http://www.sharepointdevwiki.com/display/sp2010/Site+Templates+in+SharePoint+2010
  19.  
  20.             Web oNewWebsite = oWebsite.Webs.Add(webCreateInfo);//Aplicamos los parámetros definidos a nuestro sitio del contexto cliente.
  21.             
  22.             //Cargamos nuestro objeto  
  23.             clientContext.Load(
  24.                 oNewWebsite,
  25.                 website => website.ServerRelativeUrl,
  26.                 website => website.Created);
  27.  
  28.             clientContext.ExecuteQuery();//Ejecutamos la query
  29.  
  30.             Console.WriteLine(«Server-relative Url: {0} Created: {1}», oNewWebsite.ServerRelativeUrl, oNewWebsite.Created);//Mostramos por consola la información de nuestro sitio
  31.             Console.ReadLine();
  32.         }
  33.     }

*Para saber el nombre de las plantillas de sitio que se pueden crear me he ayudado del siguiente enlace donde podemos ver la nomenclatura que se utiliza para las distintas plantillas de SharePoint 2010: http://www.sharepointdevwiki.com/display/sp2010/Site+Templates+in+SharePoint+2010

Si todo ha funcionado correctamente nos aparecerá el siguiente mensaje por consola indicándonos la url del nuevo sitio y la fecha de creación del mismo, tal y como lo hemos indicado.

image

Por último podremos acceder a nuestro sitio a través de la ruta especificada, que en nuestro caso es: http://sharepoint2010:200/SitioPrueba, donde podemos ver que este sitio cuenta con todos los parámetros definidos en su creación (Título, Descripción, Permisos…).

image

Información relacionada:

http://www.codeproject.com/Articles/60294/SharePoint-2010-Managed-net-Client-with-Client-Obj.aspx

http://praveenbattula.blogspot.com/2010/03/sharepoint-2010-client-object-model.html

http://www.tonstegeman.com/Blog/Lists/Posts/Post.aspx?List=70640fe5%2D28d9%2D464f%2Db1c9%2D91e07c8f7e47&ID=118