viernes, 28 de octubre de 2011

Cómo descargar documentos de Sharepoint rápidamente

Así como vimos una manera sencilla de publicar documentos en un servidor de Sharepoint (acceso), en esta ocasión vamos a proceder a la descarga de esos documentos.
En este proceso vamos a utilizar la clase “System.Net.WebClient” lo que implica que estas operaciones no son exclusivas de Sharepoint, sino que servirían ‘virtualmente’ para cualquier tipo de servidor web.

Al turrón

  1. Instanciamos y configuramos el objeto “WebClient”:
    WebClient objWebClient = new WebClient();    
    objWebClient.Credentials = CredentialCache.DefaultCredentials;
  2. Descargamos el documento:
    objWebClient.DownloadFile(txtSource.Text, rutaDes + "\\" + nombreArchivo);

Descargar sin permisos en la biblioteca de origen

En muchas ocasiones, las bibliotecas de Sharepoint que se utilizan como repositorio de aplicaciones tienen especificada una seguridad específica para evitar que el acceso a esa documentación se realice desde ‘fuera’ de las aplicaciones concretas. Para poder realizar el download en estos casos, tendremos que disponer de una cuenta de acceso ‘genérica’ a la biblioteca con los permisos mínimos para poder descargar documentación, y utilizar esa cuenta en la configuración de las credenciales del objeto “WebClient”:
objWebClient.Credentials = new System.Net.NetworkCredential("user","pwd","domain"); 

¿Fácil no?

Adjuntos

Descargar

jueves, 27 de octubre de 2011

Cómo subir un documento a Sharepoint rápidamente con Servicios Web

Cuando queremos utilizar Sharepoint como repositorio de documentos de nuestras aplicaciones, lo primero que tenemos que decidir es cómo queremos conectar con el servidor para almacenar dichos documentos. La decisión en sí no es muy complicada, aunque sí es cierto que dependerá de factores como arquitectura, formas de conexión, seguridad, etc…
En este artículo vamos a desarrollar paso a paso una función de ‘Upload’ utilizando los servicios web nativos de Sharepoint, en su versión 2010. Esta aproximación es la más sencilla de implementar y a continuación veremos cómo

Añadir la referencia web

Como comentaba más arriba, vamos a subir documentación a un servidor de Sharepoint mediante los Servicios Web nativos; en consecuencia, lo primero que tenemos que hacer es añadir la referencia web correspondiente en nuestro proyecto. En el ejemplo realizado se ha utilizado Visual Studio 2010, pero es perfectamente válido también para versiones anteriores.
  1. Sobre el proyecto, clic con el botón derecho del ratón, “Add Service Reference”

    image
  2. Para añadir la referencia web, hacemos clic en el botón “Advanced” y a continuación en el botón “Add Web Reference”

    image

    image
  3. En la caja de texto “URL:” introducimos la url de acceso al servicio web de Sharepoint que nos permitirá subir documentos. Dentro de todos los servicios web que proporciona Sharepoint, el que nos interesa en esta ocasión es “Copy.asmx” y como el resto de los servicios web está alojado en la carpeta “_vti_bin” en este ejemplo vamos a utilizar como ruta para la referencia “http://srvmv07/_vti_bin/copy.asmx
  4. Una vez que la ventana anterior nos ha comprobado la referencia, le damos un nombre (en el ejemplo “WSCopy”) y hacemos clic en “Add Reference” para incluir la referencia en el proyecto.

    image
En este ejemplo, vamos a trabajar con dos parámetros en el archivo de configuración. Uno indicará el sitio de Sharepoint donde queremos subir el documento (“WebUrl”) en formato http://servidor/sitio y el otro indicará la biblioteca de destino (“DocumentLibraryDestination”)

Al turrón

  1. Instanciamos el servicio web:
    //Configuración del Servicio Web         
    WSCopy.Copy copyService = new WSCopy.Copy();         
    copyService.Url = Properties.Settings.Default.WebUrl + "/_vti_bin/copy.asmx";         
    copyService.Credentials = System.Net.CredentialCache.DefaultCredentials;      
    Como podemos ver en el fragmento de código, en este ejemplo estamos utilizando las credenciales por defecto del usuario que está ejecutando el programa. Más adelante veremos cómo actuar si dicho usuario no tendrá permisos sobre la carpeta de destino.
  2. Preparamos los objetos necesarios para realizar el Upload:
    //Declare and initiates the Copy WebService members for uploading       
    string sourcePath = “Ruta completa al archivo a publicar”;       
    string[] destinationUrl = {       
                               Properties.Settings.Default.WebUrl + "/" +       
                               Properties.Settings.Default.DocumentLibraryDestination + "/" +       
                               “Nombre del archivo”       
                               };       
    WSCopy.CopyResult cResult1 = new WSCopy.CopyResult();       
    WSCopy.CopyResult cResult2 = new WSCopy.CopyResult();       
    WSCopy.CopyResult[] cResultArray = { cResult1, cResult2 };       
    WSCopy.FieldInformation fFiledInfo = new WSCopy.FieldInformation();       
    WSCopy.FieldInformation[] fFiledInfoArray = { fFiledInfo };     
    En este fragmento, la parte más relevante está en las últimas dos instrucciones, ya que nos permitirán, completando el código, establecer los valores de metadatos del documento en Sharepoint. De momento no vamos a publicar ningún atributo, así que lo dejamos como está.
  3. Abrimos el archivo que vamos a ‘subir’ y lo convertimos en un array de Bytes, que será lo que tendremos que enviar al servicio web como parámetro:
    //Reading the document contents in to stream       
    FileStream strm = new FileStream(sourcePath, FileMode.Open, FileAccess.Read);       
    byte[] fileContents = new Byte[strm.Length];       
    byte[] r = new Byte[strm.Length];       
    int ia = strm.Read(fileContents, 0, Convert.ToInt32(strm.Length));       
    strm.Close();
  4. Invocamos a la función “CopyIntoItems” del Servicio Web para realizar el upload y… listo!

    uint copyresult = copyService.CopyIntoItems(sourcePath, destinationUrl, fFiledInfoArray, fileContents, out cResultArray);

    Ojo con esta última parte, ay que según la documentación, la función devolverá “0” si todo a ido bien, y otro valor si ha habido algún problema; sin embargo, la manera de comprobar si todo ha ido bien es mediante el parámetro de vuelta “cResultArray”

Realizar el Upload sin permisos en la biblioteca de destino


En muchas ocasiones, las bibliotecas de Sharepoint que se utilizan como repositorio de aplicaciones tienen especificada una seguridad específica para evitar que el acceso a esa documentación se realice desde ‘fuera’ de las aplicaciones concretas. Para poder realizar el upload en estos casos, tendremos que disponer de una cuenta de acceso ‘genérica’ a la biblioteca con los permisos mínimos para poder subir documentación, y utilizar esa cuenta en la configuración de las credenciales del servicio web:
copyService.Credentials = new System.Net.NetworkCredential("user","pwd","domain");
 
Cuidado porque esta práctica provoca que en la biblioteca de documentos el usuario que aparece como última modificación será ese usuario genérico.

Modificar propiedades del documento


Las bibliotecas de Sharepoint pueden contener propiedades o atributos que etiquetan al contenido de las mismas. Para poder aplicar valor a esas propiedades al reaalizar el upload de un documento, tendremso que ‘jugar’ con la clase “FieldInformation” que comentaba más arriba:
fFiledInfo.DisplayName = "Nombre del atributo";
fFiledInfo.Type = WSCopy.FieldType.Text;//Tipo
fFiledInfo.Value = "valor";
 

Adjuntos

Descargar

jueves, 20 de octubre de 2011

Trabajar con archivos de configuración

Como todos sabemos, para añadir parámetros o elementos de configuración a un proyecto .NET, utilizamos los archivos de configuración (indistintamente con el archivo app.config o con el archivo web.config)
Para añadir opciones a estos archivos, disponemos básicamente de dos opciones:
  1. Entrada Manual:
    Con entrada manual me refiero a aquellas entradas que ubicamos en la sección de un archivo de configuración.

    image
    Para acceder a estos valores en tiempo de ejecución, tenemos que utilizar la clase “ConfigurationManager”, siempre que hallamos añadido la referencia correspondiente al ensamblado “System.Configuration.dll”

    image
  2. Entrada Semiautomática:
    Estas entradas son las que se establecen desde la ventana de propiedades de un proyecto.

    image
    Estas entradas se almacenan en el archivo de configuración de una manera un tanto “especial” como ya habréis observado.

    image
    Y para acceder a estos valores en tiempo de ejecución, típicamente haremos lo siguiente:

    image
Pero, ¿tenemos alguna opción adicional para trabajar con estos archivos de configuración? La respuesta es rápida y concisa: .
Si observamos las entradas que se generan en el archivo de configuración al utilizar el panel de propiedades del proyecto, vemos que añade dos elementos, por un lado un “sectionGroup” y por otro lado un “setting” en un nodo con el formato “Namespace.Properties.Settings” que coincide con el atributo “name” del elemento “sectionGroup”
La parte que más interesa ahora mismo es la del “sectionGroup” ya que si la observamos con detenimiento, podemos ver que tiene especificado un “type”, que típicamente será del estilo:
type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=key"

Además la propia entrada “section” tiene también un atributo “type”, que típicamente será del estilo:
type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=key"

Con lo anterior lo único que quiero indicar es que si los distintos elementos del archivo de configuración son de tipos concretos del Framework de .NET, ¿por qué no vamos a poder utilizar ahí tipos personalizados creados por nosotros?

En este punto, alguien puede preguntarse por qué nos interesa tener entradas personalizadas, y la respuesta, tal y como yo lo veo, hay que buscarla en el deseo de tener los archivos de configuración organizados y limpios, ya que con esta posibilidad podríamos tener distintas secciones dependiendo de módulos activados en nuestros programas, como podría ser un sistema de trazas o incluso los parámetros necesarios para utilizar componentes genéricos de acceso a datos.

Al turrón


Una vez que hemos visto un poco por encima cómo se utilizan los archivos de configuración, vamos a generar nuestros propios tipos de entradas, para poder organizar los parámetros necesarios para nuestros componentes genéricos.

Lo primero que tenemos que hacer es crear una clase personalizada “ConfigurationSection” que nos sirva para trabajar con los valores del archivo de configuración. Esta clase heredará de la clase “ConfigurationSection”, que nos permitirá trabajar con los datos en tiempo de ejecución.

El siguiente fragmento de código muestra la clase, está disponible en la sección de adjuntos:
     /// 
     /// This class allow us to access the config file data via the Configuration Manager.
     ///
     public class CustomTraceSection : ConfigurationSection
     {
         ///
         /// Create an "active" attribute.
         ///
         [ConfigurationProperty("active", DefaultValue = "false", IsRequired = false)]
         public Boolean Active
         {
             get
             {
                 return (Boolean)this["active"];
             }
             set
             {
                 this["active"] = value;
             }
         }
         ///
         /// Create a "traceLevel" element.
         ///
         [ConfigurationProperty("traceLevel")]
         public TraceLevelElement TraceLevel
         {
             get
             {
                 return (TraceLevelElement)this["traceLevel"];
             }
             set
             {
                 this["traceLevel"] = value;
             }
         }

Con este código lo que estamos generando es el soporte para nuestra sección de configuración personalizada, que quedará así:
image

Además estamos definiendo también los componentes que tendrá nuestra sección de configuración, en este caso un atributo “active” y un elemento “traceLevel”. El elemento “traceLevel” se genera mediante una clase personalizada que hereda de “ConfigurationElement”, cuyo detalle se ve a continuación, a pesar de que es muy similar a la clase anterior:

    public class TraceLevelElement : ConfigurationElement
     {
         ///
         /// Create a "value" attribute.
         ///
         [ConfigurationProperty("value", DefaultValue = "Nothing", IsRequired = true)]
         public TraceLevel Value
         {
             get
             {
                 return (TraceLevel)this["value"];
             }
             set
             {
                 this["value"] = value;
             }
         }
A destacar: En esta última clase hemos utilizado un tipo enumerado para indicar los valores disponibles para la propiedad, a título informativo de las posibilidades que nos brinda el sistema.

Con este código, ya podemos completar nuestra sección de configuración, que quedará así:
image

Ya sólo nos queda utilizar esta sección en nuestro código y lo tendremos todo ligado y bastante organizado:

            //Instanciamos la sección de configuración
            CustomTraceSection config =
                (CustomTraceSection) ConfigurationManager.GetSection("customTraceGroup/customTrace");

            //Acceso a valor concreto
            Boolean active = config.Active;

            //Acceso a valor embebido en un elemento
            TraceLevel traceLevel = config.TraceLevel.Value;


A partir de aquí, ¡a jugar!

Adjuntos

Descargar

Mejoras

  • Podríamos almacenar la ruta de la sección de configuración en una constante.
  • Podemos (tal vez en otro artículo) generar esas entradas en el archivo de configuración de forma ‘programática’, con lo que no sólo dejamos el archivos de configuración organizado, sino que además evitamos tener que poner esas entradas a mano.
  • Cualquier propuesta de mejora adicional, será bienvenida.

jueves, 6 de octubre de 2011

Utilizar IntelliTrace sin Visual Studio 2010

ATENCIÓN: Este procedimiento OBLIGA a tener licencia de Visual Studio 2010 Ultimate.
Como definición rápida (que me perdonen los puristas) el IntelliTrace es una herramienta que permite llevar un registro de todo lo que sucede con una aplicación, de forma que a posteriori somos capaces de reproducir 'exactamente' lo que pasó en una sesión concreta. La idea de esta herramienta es acabar con la mítica situación de "en mi equipo funciona" ¿quién no la ha utilizado alguna vez? Para una definición más exacta podemos visitar este enlace.
Una de las particularidades de esta herramienta es que sólamente está disponible de forma directa desde Visual Studio 2010 Ultimate, y se activa o desactiva a nivel general desde las opciones del producto:


 Bueno, como 'reza' el título de este post, esto no es estrictamente necesario, de forma que podemos utilizar también esta herramienta en equipos en los que no está instalado Visual Studio (ojo porque lo que no está permitido es utilizar esta herramienta en un entorno de producción.
Vamos al 'turrón' ¿Cómo utilizamos esta maravilla sin Visual Studio?
  1. Creamos una carpeta en una ubicación temporal y la llamamos (originales nosotros) IntelliTrace.
  2. En esta carpeta copiamos el contenido de la carpeta "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\TraceDebugger Tools"
  3. A continuación copiamos el archivo "Microsoft.VisualStudio.IntelliTrace.dll" que está en la carpeta "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies"
  4. Por último copiamos el archivo "TraceLogProfiler.dll" que está en la carpeta "C:\Program Files (x86)\Common Files\Microsoft Shared\VSTS 10.0\Trace Debugger"
  5. Ahora viene una parte 'chunga'. tenemos que obtener lo que se denomina como "CollectionPlan" que es un archivo de configuración que se genera al utilizar IntelliTrace desde Visual Studio. Para obtener este archivo, tenemos que activar el IntelliTrace (captura anterior) y configurar en esas mismas opciones el nivel de traza deseado. Cargamos un proyecto, y vamos a la carpeta "C:\Users\usuario\AppData\Local\Microsoft\VisualStudio\10.0\TraceDebugger\Settings" aquí veremos un archivo de nombre variable, que copiaremos también a la carpeta temporal y renombraremos a algo más claro, como por ejemplo "Collector.xml".
  6. Editamos este archivo con el bloc de notas, y nos aseguramos de que en las entradas "LogFileDirectory" y "DeleteLogOnExit" están configuradas de manera adecuada (ojo porque el primer parámetro puede tener que ser cambiado en la máquina en la que queremos ejecutar el IntelliTrace:


    Para más información acerca de este archivo, visitar el siguiente enlace.
Una vez hemos realizado estas operaciones, el contenido de nuestra carpeta temporal será algo parecido a esto:

Ya tenemos todo preparado para hacer la traza... Sólo queda coger esa carpeta y llevarla a la máquina en la que queremos sacar la traza, y ejecutar la herramienta desde la línea de comandos:
IntelliTrace.exe launch /cp:Collector.xml rutadelprogramaatrazar\programa.exe
Cuando el ejecutable termine, tendremos en la carpeta del IntelliTrace un archivo con extensión .iTrace, que contiene toda la información de la ejecución. Este archivo ya podemos abrirlo con Visual Studio 2010 y ahora disponemos de una 'grabación' de lo que ha pasado en la ejecución (fundamental para detectar errores)
NOTAS:
Aunque venga con Visual Studio 2010, esta herramienta NO necesita el Framework 4.0 y en principio es capaz de sacar trazas de programas desarrollados desd ela versión 2.0 del Framework en adelante.
En el equipo destino puede producirse un error al lanzar el programa, que se ve cuando al abrir el archivo de traza está vacío... Una de las causas que he visto es porque el componente "TraceLogProfiler.dll" no esté registrado en la máquina, si se da el caso, basta con ejecutar un regsvr32 TraceLogProfiler.dll
En la versión de 2010, sólamente podemos realizar trazas sobre programas compilados en 32 bits, pero instalando el Service Pack 1 en principio esta limitación ya no existe, si bien yo no he podido probarlo.
Sin embargo, sí puedo confirmar que modificando el valor de la entrada "AttachOptions" del archivo Collector.xml a Attach64Bit, el intellitrace funciona con un programa ejecutándose en 64 bits!
RESULTADO
A modo informativo, así es como se ve una traza de este estilo:


REFERENCIAS
Esta información ha sido recopilada partiendo de las siguientes entradas:
http://www.techmetadata.com/2010/04/standalone-intellitrace-from-vs-2010.html
Además más información en castellano en el blog del gran Unai Zorrilla, acceso