SharePoint 2007 + Outlook 2007: Guardar correos de forma masiva (IV)

Entradas anteriores de la serie:

SharePoint 2007 + Outlook 2007: Guardar correos de forma masiva (I)

SharePoint 2007 + Outlook 2007: Guardar correos de forma masiva (II)

SharePoint 2007 + Outlook 2007: Guardar correos de forma masiva (III)


bendervitruvio

He estado un par de días sin poder continuar con la serie, pero es que el trabajo aprieta y no siempre nos podemos dedicar a lo que más nos gusta…

Recapitulando: Cosas que necesitamos para nuestro add-in:

  • Cómo crear un complemento para Office (VSTO). visto en el post anterior.
  • Cómo registrar acciones en los menús de la aplicación host (Outlook). Lo veremos ahora.
  • Cómo conectar con un servidor MOSS/WSS con diferentes credenciales de usuario (System.Net.NetworkCredential) Esto también lo veremos ahora.
  • Cómo acceder a los sitios y listas de un site de MOSS/WSS (servicios Web de SharePoint). visto en el post anterior.
  • Cómo interpretar la información XML devuelta por los servicios (LINQ to XML). Y esto también lo veremos ahora.
  • El resto de cosas las veremos en los próximos días…

Hoy nos centraremos en mostrar cómo agregar opciones a los menús de Outlook (para lanzar nuestras acciones personalizadas), ver cómo conectar con un sitio de SharePoint con las credenciales predeterminadas, o bien proporcionando un usuario y password. Y además veremos cómo interpretar el resultado devuelto por los servicios Web, ya que el usar LINQ to XML va a facilitarnos en mucho la tarea de lidiar con XML puro y duro.

Demos un vistazo al futuro, a lo que va a ser este Add-In (solo Bender puede viajar al futuro):

1 – Una vez registradas nuestras propias acciones en el menú de Outlook, éstas permitirán guardar los elementos selecionados:

AddIn_Step1

2 – Aparecerá una ventana en la que podremos se leccionar la biblioteca de documentos y la carpeta destino:

 

 

AddIn_Step2

3 – Una vez seleccionada la carpeta, mostraremos una ventana de progreso en un hilo separado para que el usuario pueda seguir interactuando con Outlook:

AddIn_Step3

4 – Una vez terminado, si vamos a la biblioteca de documentos aparecerán los documentos (y más adelante también los metadatos):

AddIn_Step4

Vayamos por partes:

Registrar acciones en un menú de Outlook:

Registrar el menú es sencillo, sólo debemos modificar el código del evento ‘ItemContextMenuDisplay’ (como ya vimos en el post anterior), y llamar a un método ‘RegisterMenu’ que se encarga de agregar nuestras acciones al menú contextual de Outlook.

void Application_ItemContextMenuDisplay(
    Microsoft.Office.Core.CommandBar CommandBar, 
    Microsoft.Office.Interop.Outlook.Selection Selection)
{
    RegisterMenu(CommandBar, false);
}

 

 

 

void RegisterMenu(Microsoft.Office.Core.CommandBar CommandBar, bool IsFolder)
{
    Office.CommandBarPopup cmdSaveToMOSS = 
        (Office.CommandBarPopup)CommandBar.FindControl(
        missing, missing, "STSMOSS", missing, missing);
    if (cmdSaveToMOSS == null)
    {
        cmdSaveToMOSS = (Office.CommandBarPopup)CommandBar.Controls.Add(
                Office.MsoControlType.msoControlPopup, missing,
                missing, missing, false);
        if (cmdSaveToMOSS != null)
        {
            cmdSaveToMOSS.Caption = Properties.Resources.CONTEXT_MENU_CAPTION;
            cmdSaveToMOSS.Tag = "STMOSS";
            cmdSaveToMOSS.BeginGroup = true;
 
            Office.CommandBarButton btnSaveToMOSS =
                (Office.CommandBarButton)cmdSaveToMOSS.Controls.Add(
                Office.MsoControlType.msoControlButton, missing, missing, missing, missing);
 
            btnSaveToMOSS.Caption = Properties.Resources.CONTEXT_MENU_SENDBUTTON;
            btnSaveToMOSS.FaceId = 65;
            btnSaveToMOSS.Tag = IsFolder.ToString();
            btnSaveToMOSS.Style = MsoButtonStyle.msoButtonIconAndCaption;
            btnSaveToMOSS.Picture = getImage();
            btnSaveToMOSS.Click += new Microsoft.Office.Core.
                _CommandBarButtonEvents_ClickEventHandler(saveToMOSS_Click);  
            
            Office.CommandBarButton btnConfigurationMOSS =
                (Office.CommandBarButton)cmdSaveToMOSS.Controls.Add(
                Office.MsoControlType.msoControlButton, missing, missing, missing, missing);
 
            btnConfigurationMOSS.Caption = Properties.Resources.CONTEXT_MENU_CONFIGURATIONBUTTON;
            btnConfigurationMOSS.BeginGroup = true;
            btnConfigurationMOSS.Style = MsoButtonStyle.msoButtonIconAndCaption;
            btnConfigurationMOSS.Click += new Microsoft.Office.Core.
                _CommandBarButtonEvents_ClickEventHandler(configurationMOSS_Click);  
            
            cmdSaveToMOSS.Visible = true;
        }
    }
}

 

Este código crea un elemento menú y le agrega dos opciones (‘btnSaveToMOSS’ y ‘btnConfigurationMOSS’). A continuación establece sus propiedades y asigna los event handlers a sendas rutinas que se ejecutarán al pulsar sobre ellas.

void saveToMOSS_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)
{     
    CancelDefault = true;
    MessageBox.Show("Save");
}
 
void configurationMOSS_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)
{
    CancelDefault = true;
    MessageBox.Show("Config");
}

Conectar con un servidor MOSS/WSS con diferentes credenciales de usuario:

En algunas ocasiones tal vez nos interese conectar con un sitio de SharePoint y no hacer uso de las credenciales predeterminadas (por defecto el token del usuario de Windows). En estos casos, debemos hacer uso de la clase ‘System.Net.NetworkCredential’, pasando los valores de usuario y password (y opcionalmente dominio) para acceder al sitio. En este caso he creado unas sencillas funciones que devuelven un objeto de tipo ‘ICredentials’ que posteriormente usaremos en la propiedad ‘Credentials’ de los proxies de los servicios Web:

public static System.Net.ICredentials getCredentials()
{
    return System.Net.CredentialCache.DefaultCredentials;
}
 
public static System.Net.ICredentials getCredentials(string user, string password, string domain)
{
    return new System.Net.NetworkCredential(user, password, domain);
}

Interpretar el resultado devuelto por los servicios Web (LINQ to XML):

En el post anterior vimos que el resultado devuelto por los métodos de un servicio Web dista mucho de ser fácilmente interpretable, ya que nos devuelve un objeto de tipo XmlNode, de modo que debemos analizar el DOM para obtener el resultado deseado. En nuestro caso, vamos a realizar una llamada al método ‘GetWebCollection()’, que devuelve un XmlNode con los nombres de las webs (sites) de un sitio de SharePoint. Pero vamos a utilizar LINQ to XML para obtener sólo los elementos de un tipo determinado, y además vamos a obtener aquellos atributos que nos interesan. Y lo mejor es que todo se hace una sola sentencia:

public static List<SPSiteInfo> getSiteSubSites(websProxy.Webs sharePointWebs)
{
    try
    {
        XmlNode websResult = sharePointWebs.GetWebCollection();
        XDocument results = XDocument.Parse(websResult.OuterXml);
        XName name = XName.Get("Web", "http://schemas.microsoft.com/sharepoint/soap/");
        var webs = from item in results.Descendants(name)
                   select new SPSiteInfo
                       (
                       item.Attribute("Title").Value,
                       item.Attribute("Url").Value
                       );
        return webs.ToList();
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

A destacar en el código anterior el uso de un elemento XName para obtener sólo los elementos de tipo Web:

XName_Web

A continuación basta con seleccionar los atributos deseados de cada elemento XML (en nuestro caso título y url) e ir creando objetos que almacenaremos en una colección. Aquí utilizo una sencilla clase llamada ‘SPSiteInfo’ para devolver una lista genérica. Esta clase tiene sólo dos propiedades de tipo string (Title y URL) y un constructor en el que le pasamos ambos valores:

public class SPSiteInfo
{
    public string Title { get; set; }
    public string URL { get; set; }
 
    public SPSiteInfo()
    {
        //
    }
 
    public SPSiteInfo(string title, string url)
    {
        Title = title;
        URL = url;
    }
}

De este modo, ya tenemos una función que nos devuelve una colección de objetos ‘SPSiteInfo’. Emplearemos este mismo procedimiento para recuperar las bibliotecas de documentos de un sitio, las carpetas de una biblioteca de documentos, e incluso las columnas de una biblioteca de documentos.

Pero ello lo veremos en el próximo post, que hay que volver a las trincheras… 🙂

PD – Os recuerdo que al final de la serie publicaré el código fuente del proyecto de ejemplo.

** crossposting desde el blog de Lluís Franco en geeks.ms **

Leave a Reply

Your email address will not be published. Required fields are marked *