domingo, 13 de diciembre de 2009

Exportar listas de Sharepoint como Features

Hoy quiero compartir uno de los tips que utilizo muy a menudo cuando desarrollo, el de cómo exportar la definición de una lista cualquiera de SharePoint y construir una Feature para poder provisionarla en otros sitios.

Muchos podrán pensar que podemos hacer lo mismo solo guardando la lista como plantilla y después agregándola al sitio que deseemos, sin embargo, para nosotros los desarrolladores, siempre es mejor tener todo por código, y que al crear nuestro paquete de instalación (WSP), este contenga una Feature que provisione la definición e instancia de la lista, es decir, todo lo necesario para que nuestro desarrollo funcione.

Básicamente esta solución lo que hace es utilizar la API que se encuentra en las dll’s:

VSeWSS.Server.Services.dll
VSeWSS.Server.SPProxies.dll

Pasos a seguir para provisionar la definición e instancia de nuestra lista a través de una feature.

1.- El código que nos permite extraer la definición de una lista

El código principalmente utiliza la funcionalidad que ya existe en la clase SPService del ensamblado VSeWSS.Server.Services, que es instalado junto con las extensiones de Visual Studio 2008 para Windows SharePoint Services 3.0, si tu instalación fue hecha en la ruta por default, estos ensamblados se encuentran en C:\Program Files\Microsoft SharePoint Developer Tools 9.0\svc\bin.

El método ExportListDefinition, que es el que se encarga de extraer la definición de la lista en cuestión, hace uso del método GetListTemplateFileExport de la clase SPService, el cual regresa un objeto del tipo ExportFilesResponse, el cual posteriormente es utilizado como parametro en el llamado al metodo SaveAsFile de la clase SPDefinitionExporter, pero que mejor que ver el código para aclarar cualquier duda.

/// <summary>
/// Exporta la lista indicada hacia el directorio de salida
/// </summary>
/// <param name="outputdir" />
/// <param name="url" />
/// <param name="listname" />
private static void ExportListDefinition(string outputdir, string url, string listname)
{
 SPSite site = null;
 SPWeb web = null;
 try
 {
  using (site = new SPSite(url))
  {
   using (web = site.OpenWeb())
   {
    Guid g = web.Lists[listname].ID;
    SPService service = new SPService();
    ExportFilesResponse response = service.GetListTemplateFileExport(url, g);
    if (response.IfSuccess)
    {
     if (response.Entity != null)
     {
      SPDefinitionExporter exporter = new SPDefinitionExporter(outputdir, url);
      exporter.SaveAsFile(response.Entity);
     }
    }
   }
  }
 }
 catch (Exception ex)
 {
  if (web != null) web.Dispose();
  if (site != null) site.Dispose();
  throw ex;
 }
}

La clase SPDefinitionExporter

internal class SPDefinitionExporter
{
 public string ExportLocation
 {
  get;
  set;
 }

 public virtual string TargetSiteUrl
 {
  get;
  set;
 }
 // Methods

 public SPDefinitionExporter(string exportLocation, string targetSiteUrl)
 {
  this.ExportLocation = exportLocation;
  this.TargetSiteUrl = targetSiteUrl;
 }


 public void SaveAsFile(ExportFileEntity file)
 {
  if (file != null)
  {
   string path = string.Format("{0}{1}", this.ExportLocation, file.RelativePath);
   Directory.CreateDirectory(GetParentDirectoryPath(path));
   if (file.IsText)
   {
    SaveAsFile(file.ContentStr, path);
   }
   else
   {
    SaveAsFile(file.ContentBin, path);
   }
  }
 }

 public void SaveAsFile(IEnumerable<ExportFileEntity> files)
 {
  if (files != null)
  {
   foreach (ExportFileEntity entity in files)
   {
    this.SaveAsFile(entity);
   }
  }
 }

 private static void SaveAsFile(string contents, string path)
 {
  FileStream stream = File.Create(path);
  StreamWriter writer = new StreamWriter(stream, Encoding.UTF8);
  writer.Write(contents);
  writer.Flush();
  writer.Close();
  stream.Close();
 }
 private static string GetParentDirectoryPath(string path)
 {
  if (string.IsNullOrEmpty(path))
  {
   return string.Empty;
  }
  int length = path.LastIndexOf(@"\");
  return path.Substring(0, length);
 }

 private static void SaveAsFile(byte[] contents, string path)
 {
  FileStream output = File.Create(path);
  BinaryWriter writer = new BinaryWriter(output);
  writer.Write(contents);
  writer.Flush();
  writer.Close();
  output.Close();
 }
}
Para fines didacticos he creado una lista llamada Empleados, la cual servira para demostrar como extraer su definición y despues crear la feature que provisionara la definición obtenida, así como una instancia de la lista. La lista tiene la siguiente estructura:



Corriendo este programita con los siguientes argumentos

ExportListDefinition.exe -url http://siber:81 -path "c:\temp" -listname Empleados
 




2.- Creando la feature

Una vez que ya tenemos los archivos obtenidos de la utilería que exporta la definición de la lista, es tiempo de crear la feature que provisionara estos archivos en un sitio de SharePoint, para esto recomiendo utilizar algún asistente como VSeWSS 1.3, WSPBuilder, etc.

Yo utilizo WSPBuilder simplemente porque estoy más familiarizado con él, y su uso me parece mas intuitivo.

Entonces creamos la solución, agregamos una nueva feature, y creamos una jerarquía de archivos como la siguiente:











3.- Archivos complementarios

Por default al crear la feature, el asistente nos creara un archivo elements.xml, el cual renombraremos como Instance.xml, y cuya estructura es la siguiente:




También, debemos colocar el archivo ListDefinition.xml, que la utilería creó, al mismo nivel que el archivo Feature.xml y el archivo Instance.xml, a continuación como se ve el archivo Instance.xml de mi ejemplo:



Noten que he resaltado el Id de estos dos elementos, y esto es porque este Id debe ser el mismo, y debe corresponder también con el que se encuentra en el archivo schema.xml, como se aprecia a continuación:


Y ya por último, en el archivo Feature.xml debemos hacer referencia a estos 3 archivos que acabo de mencionar, en la sección ElementManifest, como se muestra a continuación:




Una vez que hagamos todo esto y despleguemos nuestra solución (WSP), en la granja de SharePoint, activamos la Feature que hemos creado. 






Y ahora en el sitio en que activamos la feature tenemos una instancia de la lista de empleados:



Pero además podemos crear una lista con el mismo template, ya que también provisionamos la lista como plantilla:









Además dejo el código, para que lo revisen.

Espero que este tip, sea de utilidad

Happy Coding!

0 comentarios:

Etiquetas

SharePoint 2010 (38) Microsoft (32) Desarrollo SharePoint (31) Gerardo Reyes Ortiz (27) SharePoint (20) SharePoint 2013 (18) Errores SharePoint (12) México (10) PowerShell (9) Silverlight (8) Visio Services (7) Features (6) MVP (6) Silverlight 3 (6) WebCast (6) Workflows (6) Configuracion SharePoint 2010 (5) D.F. (5) API REST (4) Configuracion SharePoint 2010; (4) Troubleshooting (4) Visual Studio 2010 (4) Visual studio (4) WSS (4) Web parts (4) Apps (3) Comunidad SharePoint (3) Configuración SharePoint 2013 (3) ODATA (3) SharePoint Server (3) SharePoint; Instalación SharePoint; Troubleshooting; Search Service (3) Silverlight 3.0 (3) Silverlight Toolkit (3) WebParts (3) javascript (3) jquery (3) Eventos SharePoint (2) Office 2010 (2) PeoplePicker (2) REST (2) SQL Server (2) Scripting (2) Search Service Application (2) SharePoint Designer (2) UPA (2) UPS (2) Workflows SharePoint (2) host header (2) Apps Development (1) Big Bang (1) CAS (1) CSOM (1) Codeplex (1) CompartiMOSS (1) Configuracion SharePoint 2010; Errores SharePoint (1) Configuracion SharePoint 2010; SharePoint 2010 (1) Custom Actions (1) Custom Editor Parts (1) Delegate Controls (1) Deployment (1) DisableLoopbackCheck (1) Document Library (1) Entrevista (1) Examenes de Certificación (1) Extract WSP (1) FBA (1) FS4SP (1) Fakes (1) Fast Search Server 2010 For SharePoint (1) Fiddler (1) HTTP.SYS (1) HTTPS (1) JSON (1) Language Pack's (1) Latam (1) MAXDOP (1) MCSM (1) MSExpertos (1) MVC (1) Microsoft México (1) Microsoft; Codeplex; Screencast; (1) My Sites (1) SQL Server 2012 (1) SQL Server Reporting Services (1) Screencast (1) Screencast; (1) Service Applications (1) Service Pack (1) SharePoint 2007 (1) SharePoint 2010 SP 1 (1) SharePoint API (1) SharePoint Conference (1) SharePoint Emulators (1) SharePoint Farm (1) SharePoint Health Analyzer (1) SharePoint Magazine (1) SharePoint Online (1) SharePoint Search (1) SharePoint Test (1) SharePoint; Desarrollo SharePoint (1) Shims (1) Simposio (1) Simposio Latinoamericano (1) SkyDrive Pro (1) Soporte Microsoft (1) Templates (1) Tip (1) VSeWSS (1) Virtual Machine (1) Visual Studio 2012 (1) WCF (1) WSS; IIS 7 (1) Web API (1) Web Content Management (1) Web Services (1) Windows 8 (1) Windows Live ID (1) Xml (1) appcmd (1) iOS (1) jqGrid (1) onload function (1)