Compartir a través de


Este artículo proviene de un motor de traducción automática.

Servicios de conectividad empresarial

Consumo de fuentes de OData externas con SharePoint BCS

Eric White

Servicios de conectividad de negocio (BCS) de Microsoft es una característica de Microsoft Office 2010 y 2010 de SharePoint que permite a los desarrolladores y los usuarios llevar datos a SharePoint. Superficie de datos externos en SharePoint permite a los usuarios crear aplicaciones compuestas que les dé un mejor acceso a la información crítica y facilitar las interacciones con esa información.

BCS proporciona tres mecanismos básicos que puede utilizar para incluir datos externos en SharePoint. En primer lugar, puede conectarse a y consumir las bases de datos a través de consultas SQL. De forma predeterminada, SQL Server es compatible. Con cierto trabajo, puede conectarse a MySQL, Oracle y otros sistemas de administración de bases de datos.

En segundo lugar, puede usar los servicios Web que exponen métodos que seguir los patrones específicos para los prototipos de método.

En tercer lugar, puede utilizar Microsoft.NET Framework y C# o Visual Basic código para conectarse a orígenes de datos. El enfoque más común consiste en escribir una.Conector de NET (ensamblado).

En este artículo, le mostraré el tercer enfoque: escribir una.Fuente de conector del conjunto de NET que utiliza un protocolo abierto de datos (OData).

¿Por qué un.¿Conector del conjunto de NET?

Con la creciente proliferación de fuentes de OData, es posible que deba utilizar una de dichas fuentes para habilitar la funcionalidad de interés para los usuarios. BCS no tiene una función integrada para consumir fuentes de OData, pero es relativamente fácil escribir una.NET el conector del conjunto que lo haga.

Esto también es un método para mostrar cómo escribir un.Conector de NET (ensamblado). Otro enfoque consistiría en escribir un conector personalizado para consumir una base de datos SQL, pero esto es superflua BCS puedan consumir fácilmente orígenes de datos SQL de forma inmediata. Además, para demostrar la escritura una.Conector del conjunto de NET que utiliza una base de datos requiere que instale y configure la base de datos en consecuencia. Esto no es difícil, pero agrega algunos pasos adicionales y complica el ejemplo. En cambio, escribir un.Conector del conjunto de NET que consume una fuente de OData existente puede no resultar sencillo.

Este ejemplo también muestra cómo implementar la creación, las operaciones de lectura, actualización y eliminación (CRUD) mediante OData. Verá lo fácil que es.

Probablemente se sorprenda si ve la poca cantidad de código sólo tiene que escribir para crear una.Conector del conjunto de NET que consume una fuente de OData. Tecnologías de acceso a datos han recorrido un largo camino y OData que se va a habilitar un nuevo nivel de interoperabilidad entre las aplicaciones que producen y consumen datos.

Tenga en cuenta que SharePoint designer es otro enfoque para modelar, desarrollar y publicar BCS tipos de contexto externo. SharePoint Designer admite de forma nativa generar modelos de entidad de negocio desde las bases de datos SQL back-end y servicios Web con la estructura de datos relativamente plana. Uso de SharePoint Designer simplifica (y reduce) el trabajo de desarrollo de BCS. Sin embargo, no admiten de forma nativa los servicios de OData actualmente.

OData y SharePoint

OData es un protocolo Web para consultar y actualizar los datos que se basa en tecnologías Web existentes, como HTTP, protocolo de publicación Atom (AtomPub) y JSON. OData que se sirve para exponer y tener acceso a información desde una gran variedad de orígenes de bases de datos relacionales, file systems, sistemas de administración de contenido y sitios Web de tradicionales. Para una buena introducción a OData, consulte "Edificio Rich Internet Apps con los datos protocolo abierto" (msdn.microsoft.com/magazine/ff714561), el número de junio de 2010 de msdn Magazine. El artículo fue escrito por Shane Burgess, uno de los jefes de programa en los datos y el grupo de modelos de Microsoft.

2010 Foundation de SharePoint y SharePoint Server 2010 exponen datos de la lista como una fuente de OData. Esta funcionalidad está habilitada de forma predeterminada. Si tiene un sitio de SharePoint instalado en el http://intranet.contoso.com de la dirección URL, se puede recuperar el conjunto de listas de SharePoint para el sitio, introduzca http://intranet.contoso.com/\_vti\_bin/listdata.svc en el explorador.

Si el sitio de SharePoint 2010 corporativo incluye la característica de Mi sitio y su alias, es decir, ericwhite, puede ver las listas que se exponen en Mi sitio, introduzca http://my/sites/ericwhite/_vti_bin/listdata.svc en el explorador. En cualquier caso, verá un átomo de alimentación como el de figura 1 aparece en el navegador.

OData from a SharePoint List

Figura 1 OData de una lista de SharePoint

Con el.NET Framework, que es un método sencillo para consumir una fuente de OData utilizar los servicios de datos de WCF. Utilizar Visual Studio para agregar una referencia de servicio a la fuente de OData y el IDE automáticamente genera código para que pueda utilizar las clases con establecimiento inflexible para consultar y actualizar la fuente. Pasará a través de este proceso.

Para obtener más información acerca de cómo funciona esto, consulte el centro de desarrollo de servicios de datos de WCF (msdn.microsoft.com/data/bb931106), que tiene un principiante guía y enlaces a recursos.

Introducción

Como he mencionado anteriormente, SharePoint 2010 expone los datos de la lista como canales de OData. Una forma sencilla para tener acceso a las fuentes es a través de una.Conector del conjunto de NET y yo voy a le guiará a través del proceso de creación de dicho conector.

Este proceso creará un tipo de contenido externo que puede mostrar y mantener en una lista externa. Esto puede parecer un poco divertida: una vez que el ejemplo de trabajo, tendrá un sitio de SharePoint que contiene dos listas con exactamente los mismos datos. Una de las listas será una lista de SharePoint que cree y configure el tiempo de espera de la forma habitual. La lista de otros será una lista externa que muestra los datos procedentes de la fuente para la primera lista de OData. Si Agregar o modificar registros en una de las listas, los cambios se muestran en la otra dirección.

La principal ventaja de este enfoque es que resulta sencillo generar y ejecutar el ejemplo. No es necesario instalar cualquier infraestructura para obtener un ejemplo. Todo lo que necesita es un conjunto de servidores de SharePoint para el que tenga acceso de administrador de granja de servidores.

Si no dispone de la infraestructura, la manera más fácil de ejecutar el ejemplo es descargar la demostración de trabajador de información de 2010 y la máquina Virtual de evaluación (bit.ly/gBKog8). La máquina virtual, o la máquina virtual, incluye una copia de trabajo instalada, de 2010 de SharePoint, Visual Studio de 2010, Office 2010 y mucho, mucho más. En el ejemplo se muestra en el artículo funciona sin modificaciones en esta máquina virtual.

Si tiene su propio entorno de desarrollo de SharePoint 2010, es fácil modificar este ejemplo correctamente (indicar dónde a medida que avanzo a lo largo). Sin embargo, si está iniciando en el desarrollo de SharePoint y desea probar algunos ejemplos, la máquina virtual es la mejor opción.

El primer paso para crear este ejemplo es que se familiarice con el uso de OData para manipular datos en una lista de SharePoint. En este ejemplo, que se conecta a un sistema de administración (CRM) de relación de cliente que expone una lista de clientes mediante OData.

En primer lugar, cree una lista de SharePoint que contiene unos registros que representen a los clientes.

  1. Abra un explorador, vaya a un sitio de SharePoint y crear una lista personalizada denominada a Customers.
  2. Cambiar el nombre de la columna título en CustomerID.
  3. Crear una nueva columna denominada CustomerName, con un tipo de una sola línea de texto.
  4. Crear una nueva columna denominada edad, con un tipo de número.
  5. Agregue algunos registros.

Ahora, inicie sesión en la máquina virtual como administrador e inicie Visual Studio de 2010. Cree una aplicación de consola de Windows. Para crear estos ejemplos de OData, no importa si se genera para.NET Framework 4 o.NET Framework 3.5. Sin embargo, al generar el.Conector del conjunto de NET posterior, deberá dirigirse.NET Framework 3.5 porque es la única versión compatible actualmente con SharePoint 2010. Para que Visual Studio generar clases con nombres de espacio de nombres buena, denominar este proyecto Contoso.

Más adelante en este artículo, trataré los nombres de BCS y OData.Conectores de NET (ensamblado). Existen cosas específicas que puede hacer para generar los nombres correctamente y, a continuación, en este caso, el espacio de nombres sea más lógico si el nombre del proyecto de Contoso.

En el menú de Visual Studio, haga clic en proyecto, haga clic en Agregar referencia de servicio. Escriba la dirección URL de servicio de OData del sitio de SharePoint en el cuadro de diálogo Agregar referencia de servicio. Si utiliza la máquina virtual de la demostración, la dirección URL del servicio es http://intranet.contoso.com/\_vti\_bin/listdata.svc.

Si se conecta a un sitio de SharePoint en una dirección URL diferente, necesitará ajustar la dirección URL de servicio según corresponda.

Haga clic en Ir. Visual Studio intentará ir a la ubicación y descargar metadatos desde el sitio de SharePoint. Si se realiza correctamente, mostrará el nombre de servicio en la lista de servicios en el cuadro de diálogo Agregar referencia de servicio. Puesto que está simulando un sistema CRM, hay que introducir Crm en el espacio de nombres campo. Haga clic en Aceptar. Es interesante examinar el código generado. Haga clic en el botón Mostrar todos los archivos en la ventana del explorador de soluciones, a continuación, expanda el espacio de nombres de Crm, expanda Reference.datasvcmap y abra Reference.cs. Tendrá este aspecto (eliminan los comentarios para mayor claridad):

namespace Contoso.Crm {
  public partial class TeamSiteDataContext : 
    global::System.Data.Services.Client.DataServiceContext {
    ...

Debido a cómo se denominan el proyecto y el espacio de nombres de referencia de servicio, el espacio de nombres para las clases generadas es Contoso.Crm. El nombre completo de la clase para la lista de los clientes es Contoso.Crm.Customers, que tiene sentido.

Tenga en cuenta también el nombre generado para el contexto de datos. En este caso, es TeamSiteDataContext. El nombre generado de esta clase se basa en el nombre del sitio de SharePoint que se conecta. En el caso de la máquina virtual de la demostración, el nombre del sitio predeterminado que se conecta es sitio de grupo. Si su entorno es diferente, anote el nombre de la clase de contexto de datos para que puedan modificar código en ejemplos de forma adecuada.

Abrir Program.cs y actualizarlo con el código mostrado en figura 2. Si no utiliza la máquina virtual de la demostración, ajuste la dirección URL del servicio OData en consecuencia. Compile y ejecute el programa para ver los resultados de la consulta. Como puede ver, no tardará mucho código para recuperar datos de una lista utilizando OData.

Figura 2 actualiza el código para Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using Contoso.Crm;

class Program {
  static void Main(string[] args) {
    TeamSiteDataContext dc =
      new TeamSiteDataContext(new Uri(
      "http://intranet.contoso.com/_vti_bin/listdata.svc"));
    dc.Credentials = CredentialCache.DefaultNetworkCredentials;
    var customers = 
      from c in dc.Customers
      select new {
        CustomerID = c.CustomerID,
        CustomerName = c.CustomerName,
        Age = c.Age,
      };
    foreach (var c in customers) 
      Console.WriteLine(c);
  }
}

Operaciones CRUD con OData

Ahora vamos intente insertar de un cliente. Necesitará el código crear un nuevo CustomersItem e inicializar sus valores. A continuación, llama al método TeamSiteDataContext.AddToCustomers, pasando el objeto CustomersItem como un parámetro. Por último, para confirmar los cambios llamará la TeamSiteDataContext.SaveChanges.

En Program.cs, reemplace el bucle de foreach y de declaración de variable de un clientes con el código siguiente:

CustomersItem cust = new CustomersItem();
  cust.CustomerID = "JANE08";
  cust.CustomerName = "Jane";
  cust.Age = 22;
  dc.AddToCustomers(cust);
  dc.SaveChanges();

Para actualizar a un cliente, podrá consultar la lista de clientes, recuperar el cliente concreto para actualizar. A continuación, actualice las propiedades según corresponda. Llame al método TeamSiteDataContext.UpdateObject. Por último, llame a la TeamSiteDataContext.SaveChanges para confirmar los cambios:

CustomersItem cust = dc.Customers
    .Where(c => c.CustomerID == "BOB01")
    .FirstOrDefault();
  if (cust != null) {
    cust.CustomerName = "Robert";
    dc.UpdateObject(cust);
    dc.SaveChanges();
  }

Para eliminar a un cliente, consultar la lista de clientes, recuperar el cliente concreto para eliminar.Llame al método TeamSiteDataContext.DeleteObject.Llame a la TeamSiteDataContext.SaveChanges para confirmar los cambios:

CustomersItem cust = dc.Customers
  .Where(c => c.CustomerID == "BILL02")
  .FirstOrDefault();
if (cust != null) {
  dc.DeleteObject(cust);
  dc.SaveChanges();
}

Como puede ver, modificar una lista de SharePoint con OData es sencillo.

Creación de una.Conector del conjunto de NET

En el proceso de creación del.Conector del conjunto de NET, define una clase que representa la entidad que se va a exponer como un tipo de contenido externo. En este ejemplo, define una clase de cliente que representa un elemento en la lista de los clientes. Algunos métodos, como, por ejemplo, el método para crear a un cliente, toman una instancia de esta clase como un argumento. Otros métodos, como, por ejemplo, el método para devolver a todos los clientes en la lista, devuelven una colección de instancias de esta clase.

También podrá configurar un modelo BCS que describe esta clase en un dialecto XML. La infraestructura subyacente BCS utilizará la información en la definición XML del modelo de BCS para que el tipo de contenido externo es utilizable desde dentro de SharePoint (2010).

Si hay un punto clave que debe llevarse del presente artículo, esto es: debe hacer coincidir exactamente con la clase definida real del modelo.

Existen herramientas que le ayudarán a hacer que la definición de modelo BCS coincide con la clase real. Sin embargo, el punto clave es que a través de un enfoque u otro, debe validar cuidadosamente que el modelo coincide con la clase real.

En una implementación más típica de BCS, podrá definir muchas de estas clases y todas ellas en la definición del modelo BCS del modelo. La mayor parte del trabajo al implementar una solución BCS compleja es hacer que el modelo coincide con las clases.

Ahora Generemos ahora el conector. En este ejemplo sólo creará una de sólo lectura.Conector del conjunto de NET, pero una vez ha visto los conceptos básicos, debe ser sencilla agregar el resto de las funciones CRUD.

La descarga de código de este artículo incluye el código y el modelo BCS para la funcionalidad CRUD; funciona sin modificaciones en la demostración de la máquina virtual.

Inicie sesión en el equipo de desarrollo de SharePoint como administrador. Debe tener derechos de administrador de granja de servidores para crear e implementar una.Conector de NET (ensamblado).

Inicie Visual Studio 2010. Cree un nuevo proyecto. Cree una nueva aplicación de modelo (BDC) de conectividad de datos de negocio de SharePoint 2010. Como antes, debe seleccionar como destino el.NET Framework 3.5. Denomine el proyecto Contoso y haga clic en Aceptar. Una vez más, vamos a utilizar el nombre del proyecto Contoso, que se utilizará en el espacio de nombres.

En el Asistente para la personalización de SharePoint puede introducir una dirección URL de sitio local de un sitio de SharePoint para la depuración. En este asistente en la máquina virtual de la demostración, la dirección URL está establecida correctamente de forma predeterminada a http://intranet.contoso.com. Cambiar esta dirección URL si está trabajando con un sitio de SharePoint en una dirección distinta. El asistente también permite saber que este proyecto se implementará como una solución de conjunto de servidores. Haga clic en Finalizar. Espere un poco para que ejecute el asistente.

Cambie el nombre de los nodos del modelo BDC en el Explorador de soluciones de BdcModel1 a ContosoBdcModel.

A continuación, abra el panel Explorador de BDC (de forma predeterminada, junto al explorador de soluciones). Cambie el nombre de los tres nodos de BdcModel1 a ContosoBdcModel. En el Explorador de BDC, no puede renombrar directamente cada nodo de árbol del control. En su lugar, debe seleccionar cada nodo y, a continuación, modifique el nombre en el panel de propiedades
(véase figura 3).

Changing Model Names

Figura 3 cambiar nombres de modelo

El siguiente paso es cambiar el nombre de la entidad y especificar el identificador de la entidad. Seleccione Entity1 en el diseñador BDC. Después de seleccionar la entidad, puede cambiar su nombre en el panel Propiedades. Cambiar su nombre a los clientes y cambie su espacio de nombres a Contoso.Crm.

En el Diseñador de BDC, haga clic en identificador1 y cambie su nombre a CustomerID. También deberá diseñar la entidad en el Explorador de BDC. Esta parte debe realizarse de forma precisa. Si hay una discrepancia entre el modelo de BDC y la clase real que se va a utilizar, los resultados son indefinidos y mensajes de error no se iluminan siempre. En algunos casos, la única pista a cuál es el problema es que no se pudo cargar la lista de elementos Web para el tipo de contenido externo.

Expanda los nodos en el Explorador de BDC hasta que pueda ver el nodo de identificador1 en el parámetro id del método ReadItem. Cambie su nombre a CustomerID. Expanda el árbol hasta que pueda ver el nodo Entity1 en el returParameter para el método ReadItem. Cambie el nombre de la entidad a los clientes y, a continuación, cambie el nombre de tipo Contoso.Crm.Customers, ContosoBdcModel.

Va a redefinir completamente de la entidad de cliente, así que elimine los nodos identificador1 y mensaje de la entidad de los clientes.

Haga clic en los clientes y haga clic en Agregar el Descriptor de tipos. Cambiar el nombre del descriptor de tipos nuevos a CustomerID. De forma predeterminada, se establece el tipo de un nuevo descriptor de tipos para System.String, que es lo que desea para este ejemplo. En el panel Propiedades, desplácese hacia abajo hasta que aparezca el campo de identificador. Utilice la lista desplegable para cambiar su valor en CustomerID.

De nuevo, haga clic en los clientes y haga clic en Agregar el Descriptor de tipos. Cambie el nombre CustomerName. Su tipo es System.String, que es correcta.

Agregar otro descriptor de tipos, cambie el nombre a la edad y cambia el tipo System.Int32. Después de realizar estos cambios, se parecerá el panel Explorador de BDC figura 4. Expanda el nodo ReadList, expanda el nodo returnParameter y cambie el nombre Entity1List a CustomersList. El nombre de tipo se establece en el siguiente:

System.Collections.Generic.IEnumerable`1[[Contoso.BdcModel1.Entity1, ContosoBdcModel]]

The Completed Customers Entity

Figura 4 la entidad clientes completado

Esta sintaxis, formada por el acento invertido seguido de uno (1) es el que representa una clase genérica con un parámetro de tipo.El tipo que sigue en los corchetes dobles está formado por un nombre de tipo completo, así como el nombre del modelo del modelo de BDC que contiene el tipo de.Cambiar el nombre de tipo para:

System.Collections.Generic.IEnumerable`1[[Contoso.Crm.Customer, ContosoBdcModel]]

Esto corresponde a un tipo de IEnumerable <Contoso.Crm.Customer>, donde se encuentra el tipo de cliente en el ContosoBdcModel.

Elimine el nodo de Entity1 que es hijo del nodo CustomersList. Copie la entidad de los clientes que recientemente configurado como un descriptor de tipos de hijo de la returnParameter del método ReadItem.

Seleccione el nodo de CustomersList que se encuentra en la returnParameter del método ReadList y pegue la entidad Customers.

Volver a la ventana del explorador de soluciones y modificar el archivo Feature1.Template.xml. Agregue una propiedad SiteUrl con un valor de la dirección URL del sitio de SharePoint:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="https://schemas.microsoft.com/sharepoint/">
  <Properties>
    <Property Key="GloballyAvailable" Value="true" />
    <Property Key="SiteUrl" Value="http://intranet.contoso.com" />
  </Properties>
</Feature>

Cambie el nombre Entity1.cs a Customers.cs. Reemplace el contenido de Customers.cs con el código siguiente, que define la entidad de cliente para el conector del conjunto:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Contoso.Crm {
  public partial class Customer {
    public string CustomerID { get; set; }
    public string CustomerName { get; set; }
    public int Age { get; set; }
  }
}

Reemplace el código en CustomersService.cs con el código en figura 5, que define los métodos que recuperar un único elemento y recuperar una colección de elementos.

Figura 5 CustomersService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using Contoso.Crm;

namespace Contoso.Crm {
  public class CustomersService {
    public static Customer ReadItem(string id) {
      TeamSiteDataContext dc = new TeamSiteDataContext(
        new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
      dc.Credentials = CredentialCache.DefaultNetworkCredentials;
      var customers = 
        from c in dc.Customers
        where c.CustomerID == id
        select new Customer() {
          CustomerID = c.CustomerID,
          CustomerName = c.CustomerName,
          Age = (int)c.Age,
        };
      return customers.FirstOrDefault();
    }

    public static IEnumerable<Customer> ReadList() {
      TeamSiteDataContext dc = new TeamSiteDataContext(
        new Uri("http://intranet.contoso.com/_vti_bin/listdata.svc"));
      dc.Credentials = CredentialCache.DefaultNetworkCredentials;
      var customers = 
        from c in dc.Customers
        select new Customer() {
          CustomerID = c.CustomerID,
          CustomerName = c.CustomerName,
          Age = (int)c.Age,
        };
      return customers;
    }
  }
}

Los procedimientos que he descrito al principio de este artículo, agregue una referencia de servicio al sitio, especifica un espacio de nombres de Crm. Haga clic en Aceptar. Genere la solución haciendo clic en generar | Generar Contoso. Ahora implementar la solución haciendo clic en generar | Implementar Contoso.

Conceder permisos para todos los usuarios autenticados tener acceso a este tipo de contenido externo. Abra Administración Central y, a continuación, haga clic en administrar aplicaciones de servicio. Haga clic en el servicio de conectividad de datos de negocio. Haga clic en la flecha abajo junto al tipo de contenido externo que acaba de agregar y, a continuación, haga clic en establecer permisos. Haga clic en el botón Examinar, justo debajo del cuadro de texto. Haga clic en todos los usuarios y, a continuación, haga clic en todos los usuarios autenticados. Haga clic en el botón Agregar y, a continuación, haga clic en Aceptar.

En la ventana Definir permisos de objeto, haga clic en el botón Agregar y, a continuación, establezca permisos para editar, Execute, seleccionable en clientes y establecer permisos. Haga clic en Aceptar.

Visite el sitio de SharePoint. Crear una nueva lista externa. Especificar CustomersExt para el nombre de la lista. Haga clic en el Explorador de tipo de contenido externo. En el selector de tipo de contenido externo, haga clic en el tipo de contenido externo que acaba de crear. Si utiliza la máquina virtual de la demostración, el tipo de contenido que acaba de crear será el tipo de contenido externo sólo en la lista. Haga clic en Aceptar.

Haga clic en el botón Crear, espere un poco y, si todo va bien, verá una nueva lista externa que contiene los mismos datos que la lista de los clientes.

Si agrega un registro a la lista normal, verá aparece en la lista externa. Que puede hacer pruebas con los datos de un bit. Agregar, eliminar o cambiar algunos registros en la lista de SharePoint normal y ver los datos que aparecen en la lista externa.

Reunir las piezas

Como ha visto, es bastante fácil de usar servicios de datos de WCF para consultar y modificar un OData de alimentación. También es un proceso sencillo para crear un tipo de contenido externo a través de una.Conector de NET (ensamblado). Puede conectarse a cualquier origen de datos con una.Conector de NET (ensamblado).

Esto era un ejemplo sencillo que emplea un origen de datos fácilmente accesibles, pero el modelo se extiende fácilmente a cualquier origen de datos con una fuente de OData. Para más información sobre la personalización de BCS, consulte la página de MSDN Library "Negocio conectividad servicios howtos y tutoriales" (msdn.microsoft.com/library/ee557949). También hay un tesoro de información sobre OData en el centro de desarrolladores de MSDN datos (msdn.microsoft.com/data/bb931106) y el sitio de Protocolo de datos abierto (odata.org).

Eric White es un desarrollador de software independiente y autor con 25 años de experiencia en desarrollo de aplicaciones empresariales en una gran variedad de plataformas. Actualmente está especializado en tecnologías de Microsoft Office, incluido el desarrollo de cliente de XML abierto, SharePoint y Office. Puedes seguir en Twitter en twitter.com/EricWhiteDev o en su blog en ericwhite.com/blog.

Gracias a los siguientes expertos técnicos por su ayuda en la revisión de este artículo: Ying Xiong