SharePoint Latin Rotating Header Image

Windows SharePoint Services

Usando los controles de SharePoint en WebParts

Sin duda, con el poder viene la responsabilidad. En pasados días publiqué un post acerca de cómo utilizar los controles de ASP.NET y toda su experiencia gloria dentro de WebParts de SharePoint. Sin embargo, al utilizar esta estrategia un conjunto de consideraciones subsecuentes deberán ser contempladas como hacer uso de los mismos controles SharePoint dentro de estos WebParts.


En ese sentido, debido a que sin problema alguno puedo utilizar el GridView y/o cualquier control ASP.NET al principio suena atractiva la posibilidad pero como siempre la realidad se asoma y nos muestra al que un día fue novedoso control Calendar de ASP.NET y con todo el debido respeto, hoy no es la mejor opción para la captura de una fecha dentro de una forma en SharePoint, al menos la mejor opción es usar el mismo control que se usa en SharePoint, ¿estás de acuerdo?


Vamos a nuestro Web User Control y registramos los controles web de SharePoint. Estos son los controles mejorados que SharePoint internamente utiliza en su capa de presentación.


image


Después dentro de nuestro código Markup agregamos el control SharePoint que requerimos:


image


Lo interesante es que tenemos una gama de controles de SharePoint disponibles.


image


A continuación dentro del código hacemos referencia al control de SharePoint para poder adjuntar algún evento o leer su valor.


image


Y el resultado es:


image


Estos controles cuentan con validaciones, propiedades y eventos que podemos utilizar a nuestro favor. Créditos a Luis Edmundo Teos por el reto y escenario.


Suerte!

Programación ASP.NET en WebParts de SharePoint

Si eres un de desarrollador ASP.NET que se está iniciando en desarrollo SharePoint este ejemplo puede ser de utilidad. Básicamente, usaremos un enfoque de desarrollo de WebParts basado en el uso de Web User Controls de ASP.NET 2.0.

Antes que nada utilizaremos las siguientes herramientas:

Dentro de nuestro servidor de desarrollo SharePoint cargamos Visual Studio 2008 y elegimos la creación de un proyecto SharePoint en blanco, este proyecto lo nombraremos ASPNETWebPart.

clip_image002

Especificaremos que el nivel de confianza de esta solución SharePoint sea Full Trust y la razón es que usaremos un método Page.LoadControl que requiere de permisos elevados para ejecutarse, me parece que la razón es porque este método lee de la ruta de archivos SharePoint “12 hive” y para ello requiere que el proceso w3wpg.exe solicite los permisos necesarios.

clip_image004

Usando la solución generada por Visual Studio 2008 dentro del Solution Explorer agregamos un nuevo Empty Web Site de ASP.NET llamado ASPNETWebPArtsWebSite ubicándolo en la misma carpeta creada por nuestro proyecto anterior.

clip_image006

Dentro de nuestro proyecto ASPNETWebPartWebSite agregamos un Web User Control llamado ASPNETWebUserControl y es muy importante que no deseleccionemos el cuadro de verificación Place Code in separate file.

clip_image008

Esto nos crea un simple archivo con extensión .ascx dentro de nuestro proyecto ASP.NET. A estas alturas podremos realizar cualquier funcionalidad ASP.NET. Solo hay que asegurarnos de no generar dependencias a otras carpetas como App_Code, tratemos de generar todo el código y funcionalidad sobre el Web User Control. En mi caso usare las características de vinculación de controles de ASP.NET para crear el más humilde de los GridView de ASP.NET. Podemos crear una página Defaullt.aspx para probar el funcionamiento del mismo. A continuación agregare un cuadro de texto , un botón y un label.

clip_image010

El resultado es un código Markup que podría tener sin duda código C#. En la sección de Script runat=”Server” estarían los eventos disparados por los controles de nuestro Web User Control. Solo que para propósitos de este ejemplo quiero hacer que los eventos sean disparados desde un WebPart de SharePoint y no necesariamente desde aquí.

A continuación en nuestro proyecto SharePoint agregamos un elemento de tipo Template, el cual nos creara un archivo dentro de la ruta interna de archivos de SharePoint o más conocida como 12 hive “C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\”.

clip_image012

Eliminamos el archivo generado TemplateFile.txt y agregamos la carpeta CONTROLTEMPLATES y dentro la carpeta ASPNETWebParts. Esto permite incluir en nuesdttro paquete de deployment generado por nuestro proyecto SharePoint una nueva carpeta que será aprovisionada de forma confiable en la ruta 12 hive de cada Web Front End de la granja SharePoint. Agregara una nueva carpeta llamada ASPNETWebParts. Dentro de esta carpeta agregaremos como elemento existente nuestro archivo .ascx. El resultado es algo asi:

clip_image014

Ya casi terminamos, a continuación agregamos el código de un WebPart de SharePoint que nos permitirá cargar en tiempo de ejecución el .ascx recién desarrollado. Dentro de nuestro proyecto ASPNETWebPart damos clic derecho y agregamos un nuevo elemento de tipo Web Part bajo el nombre ASPNETWebPart. En realidad puede ser cualquier nombre.

clip_image016

Abrimos el código de nuestro WebPart y agregaremos lo siguiente:

  1. Una variable miembro de tipo UserControl, esta se utilizara como un placeholder de todo el ASPNETWebUserControl.ascx.
  2. Sobre escribimos el método Render para escribir en el flujo de salida de nuestro WebPart el contenido del WebUserControl.
  3. Múltiples variables miembro que representan cada uno de los controles que existen en nuestro archivo ASPNETWebUserControl.ascx
  4. En el evento CreateChaldControls hacemos una instancia de UserControl mediante Page.LoadControl y de cada uno de los controles;

Básicamente podremos tener el control de la funcionalidad desde el WebPart y esto facilita el hacer uso del modelo de objetos de SharePoint para leer datos de otras listas o hacer querys que podamos usar para después presentarlos en el Web User Control.

using System;

using System.Runtime.InteropServices;

using System.Web.UI;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Serialization;

using Microsoft.SharePoint;

using Microsoft.SharePoint.WebControls;

using Microsoft.SharePoint.WebPartPages;

namespace ASPNETWebPart

{

[Guid("7625d718-fb33-4bbc-b05f-2f1ff0dd4a88")]

public class ASPNETWebPart : System.Web.UI.WebControls.WebParts.WebPart

{

public ASPNETWebPart()

{

this.ExportMode = WebPartExportMode.All;

}

protected override void Render(HtmlTextWriter writer)

{

this.ascxControl.RenderControl(writer);

}

UserControl ascxControl;

Button button1;

TextBox textbox1;

Label label1;

GridView gridView1;

protected override void CreateChildControls()

{

base.CreateChildControls();

ascxControl = (UserControl)Page.LoadControl(@"/_controltemplates/ASPNETWebParts/ASPNETWebUserControl.ascx");

button1 = (Button)this.ascxControl.FindControl("Button1");

textbox1 = (TextBox)this.ascxControl.FindControl("TextBox1");

label1 = (Label)this.ascxControl.FindControl("Label1");

gridView1 = (GridView)this.ascxControl.FindControl("GridView1");

button1.Click += new EventHandler(button1_Click);

this.Controls.Add(ascxControl);

}

void button1_Click(object sender, EventArgs e)

{

label1.Text = textbox1.Text;

}

}

}

El resultado:

clip_image018

Intranet-extranet de SharePoint en 40 minutos

En las últimas semanas colegas programadores que no conocen SharePoint 2007 se acercan para preguntar y evaluar si SharePoint puede dar una solución aceptable para escenarios donde usuarios externos (fuera del directorio activo) a la organización colaboren con usuarios internos (dentro del directorio activo) en algún proceso de negocio relevante para la organización.


Afortunadamente SharePoint 2007 fue construido utilizando .NET Framework 2.0/3.0 y sobre ASP.NET 2.0 por lo tanto las características que cualquier programador ASP.NET 2.0 conoce prácticamente las tenemos disponibles en SharePoint 2007, aunque esto no necesariamente aplica para la experiencia de desarrollo Sad smile.


Dicho lo anterior, tuve un par de reuniones explicando como sí SharePoint 2007 podría habilitar el escenario mencionado, sin embargo, por más que lo explico y lo justifico, no hay mejor opción que demostrarlo. Es por eso que me di a la tarea de grabar un video de cómo configurar una Intranet que hace uso de directorio activo como su fuente de credenciales de usuario y Extranet que hace uso Membership y Role Providers de ASP.NET 2.0 para gestionar usuarios en bases de datos SQL utilizando las características de Form Base Authentication. En el proceso podran visualizar como la Herramienta Central de Administracion de SharePoint aprovisiona base de datos de contenido, web sites de IIS y application pool. Smile



NOTA: Es muy importante mencionar que ninguna intranet-extranet que se utilice empresarialmente en escenarios de producción quedara configurada en 40 minutos, hay aspectos de planeación, configuración y seguridad que se deben de contemplar muy seriamente.


Y para terminar un poquito de arquitectura basica sobre un escenario en cuestion:


  • SPDB: Database Server
  • SPAPP: SharePoint Application Server
  • SPWFE1: Web Front End en Zona Intranet
  • SPWFE2: Web Front End en Zona Extranet
  • AD: Directorio Activo
  • EX: Exchange
  • ISA: ISA Server o firewall fisico

image


Como se refiere en la imagen, tenemos servicios dos zonas, Intranet y DMZ. Intranet hace uso de los recursos de red internos de la organización como directorio activo o servidor de correo electrónico, entre otro. En la misma zona interna tenemos una Topologia Small Farm de SharePoint con un solo Web Front End que usuarios internos podran acceder mediante http://intranet.splatin.com. En la zona DMZ tenemos otro Web Front End unido a la granja filtrado por un firewall hacia adentro y hacia afuera. Puede ser firewall de software como el caso de ISA Server o de hardware. Podriamos pensar que el Web Front End de la zona DMZ tenga 2 tarjetas de red, una para trafico externo con IP publica y dominio como http://extranet.splatin.com, y otra tarjeta para trafico interno con IP privada o de la red local. Aqui tenemos otras alternativas de configuración mas sofisticadas que el area de infraestructura seguramente podra aprovisionar. Usuario con acceso a internet llega al Web Front End de la zona DMZ pasando por el firewall.


Para ti que eres programador ASP.NET y estas evaluando SharePoint espero sea de utilidad este breve ejemplo acercamiento de solución.


HG

Cuantos ingenieros se necesitan para cambiar una bombilla o crear sitios SharePoint

No es curioso, es un hecho que en el ambiente laboral relacionado con tecnologías de información y seguramente en muchos otros, nos encontramos con diversas personalidades, temperamentos y arquetipos colaborando día con día para resolver algún problema técnico o de negocio. Las personas tenemos toda una historia distinta, además de cualidades que en parte de forma consiente o inconsciente constituye la forma muy particular de ver y reaccionar ante vida, en algunos casos estas cualidades son las adecuadas para ciertos escenarios pero que en definitiva en otros no lo son.

Entonces la pregunta es, ¿cómo aprovechar lo que cada quien aporta para generar valor empresarial?, esa es una pregunta que especialistas en Management, Leadership y Coaching podrían responder sin ningún problema. Sin embargo, desde mi óptica por lo menos compartir constantemente una visión compartida con lineamientos claros es esencial para organizar y aprovechar lo que cada persona con su historia histeria y experiencia aporta.

En esta historia, el requerimiento es crear un conjunto finito de sitios con las siguientes características:

  • Cada sitio se basa en la plantilla de sitio de Trabajo en Equipo
  • Cada sitio no deberá tener herencia de permisos
  • Cada sitio deberá contar con 4 grupos “Owners, Visitors, Members, Permissions” bajo la nomenclatura “Sitio + Nombre de grupo
  • Cada sitio cuenta con usuarios específicos para cada grupo.

Lo que piensan los miembros del equipo de TI:

  • Miembro 1 – Vamos a lucirnos con la solución, hagamos un WSP con feature receiver a nivel sitio web para que cuando le den activar en las características del sitio, programáticamente los construya y configure.
  • Miembro 2 – ¿Hay urgencia por parte del cliente como para dedicar tiempo a construir y probar un WSP?, ¿se va a reutilizar la jerarquía en algún otro sitio en el futuro?, ¿conviene dejar archivos en el 12 hive y un ensamblado en el GAC con full trust assembly?, ¿vamos a implementar en DEV, QA, UAT y PROD el WSP? Yo digo que construyamos los sitios manualmente usando el UI de SharePoint.
  • Miembro 3 – Usemos scripts en un archivos *.bat que ejecute el comando stsadm.exe para crear los sitios y grupos, pasamos parámetros e nivel comando y creamos un solo archivo que cuente con todas las instrucciones necesarias.

Después los miembros dan inicio a los argumentos técnico-personales para defender su postura a capa y espada, como si fueran program managers de microsoft, correos electrónicos empiezan a fluir con preguntas que toman minutos leer y escribir de regreso para ser enviados de nuevo. El tiempo pasa, el tema sube de nivel, siguen estancados, el usuario pregunta por sus sitios y en eso Miembro 2 lo toma personal, sube de nivel su contestación y claudica ante su postura. Miembro 1 ratifica la postura de Miembro 2 con el afán de no afectar al equipo y Miembro 3 procede a ejecutar la postura del Miembro 2. Tiempo total transcurrido 2.5 horas.

Si lo analizamos, todos pierden. El espíritu del equipo se deteriora, definitivamente se ve mal y el usuario de plano esperando. Realmente cualquier postura es aceptable y totalmente factible, cada una con sus peculiaridades, estimaciones, esfuerzos y consecuencias.

Dicho esto, tengo 2 preguntas:

  1. ¿Cómo podríamos contextualizar las cosas para asegurar que antes de dar inicio a una solución construida por ingenieros, todos estén viendo hacia el mismo lugar? Esa es una respuesta que probablemente podamos encontrar aquí http://www.crecenegocios.com/los-objetivos-de-una-empresa/
  2. ¿Qué estrategia técnica conviene utilizar para un escenario donde el resultado se requiere de inmediato? A veces me pregunto si mi trabajo es preguntar, sin embargo haciendo un intento de posible respuesta, dejo algunos cuestionamientos respecto al escenario planteado y claro, su implementación.

Construyendo sitios de forma manual

Pros

  • Rápida ejecución usando UI de SharePoint
  • Cero dependencia a código, ensamblado o XMLs, todo queda en la base de datos usando los site definitions y templates propietarios de SharePoint que si están considerados para ser migrados y respaldados

Cons

  • No es repetible
  • Requiere de intervención manual para replicar en cada ambiente y por lo tanto hay margen de error

Implementación

Ubicados en el sitio en cuestión accedemos a Acciones de sitio, Configuración del sitio, Toda la configuración del sitio y al de final las galerías elegimos crear sitios o área de trabajo. Especificamos el nombre, url y los siguientes puntos:

Crear sitio Configurar grupos
image image

 

Construyendo sitios programáticamente

Pros

  • Total portabilidad a múltiples ambientes y sitios con mínimo esfuerzo de implementación
  • Aprovisionamiento y des aprovisionamiento flexible de la funcionalidad y dependencias

Cons

  • Crea una dependencia a un WSP, ensamblado en GAC y archivos en 12 hive
  • Requiere de construcción, pruebas, empaquetamiento y puesta en marcha en cada ambiente
  • Pasa a control de versiones y gestión

Implementación

En este caso vemos que utilizamos una colección especial de tipo diccionario para almacenar la URL y Nombre del sitio que deseamos crear. Existen varias formas de hacer lo mismo, en este caso recorremos la colección de plantillas SharePoint para poder elegir la que usaremos “Team Sites”. Recorremos la colección de nuestro diccionario y utilizamos la colección Webs para agregar un nuevo site pasando los argumento recolectados, lo mas importante destacar en este punto es que el ultimo argumento false indica que no se mantiene la herencia y a continuación ya dentro del sitio rompemos la herencia, posteriormente recorremos el arreglo que tiene el nombre de los grupos que estaremos construyendo programáticamente, ese código se los debo y si alguien quiere compartirlo adelante.

           uint        lcid_english = 1033;
            string      siteUrl = "http://portal.litwareinc.com";
            string[]    groupTypeNames = {"Owners","Members","Permissions","Visitors"};

            Dictionary<string, string> targetSites = new Dictionary<string, string>();
            targetSites.Add("demo1", "Sitio de demostracion 1");
            targetSites.Add("demo2", "Sitio de demostracion 2");
            targetSites.Add("demo3", "Sitio de demostracion 3");
                    
                using (SPSite site = new SPSite(siteUrl))
                {
                    SPWebTemplate siteTemplate = null;
                    SPWebTemplateCollection templateCollection = site.GetWebTemplates(lcid_english);
                    
                    foreach (SPWebTemplate template in templateCollection)
                    {
                        if (template.Title.Equals("Team Site"))
                        {
                            siteTemplate = template; 
                            break;
                        }
                    }

                    using (SPWeb web = site.OpenWeb())
                    {
                        foreach (KeyValuePair<string, string> siteInfo in targetSites)
                        {
                            using (SPWeb newWeb = web.Webs.Add(
siteInfo.Key, 
siteInfo.Value, 
string.Empty, 
lcid_english, siteTemplate, false, false))
                            {
                                newWeb.BreakRoleInheritance(false);
                                newWeb.Update();

                                foreach(string groupTypeName in groupTypeNames)
                                {
                                    string groupType = string.Format("{0} {1}",siteInfo.Value,groupTypeName);
                                    
                                    // aqui deberas crear el grupo y asignar los permisos         
                                }                                                                  
                            }                            
                        }
                    }                
                } 



Construyendo sitios con comandos stsadm.exe


Pros


  • Reutilización moderada e intervención manual para especificar sites, groups que se aprovisionaran por los comandos
  • Fácil de corregir y reaccionar ante cualquier error
  • La forma recomendada por Microsoft

Cons


  • Crea una dependencia al script que ejecuta los comandos de staadm.exe para la estructura solicitada
  • Pasa a control de versiones y gestión

Implementación


En esta alternativa utilizamos las sentencias del comando stsadm.exe ubicado en c:\program files\common files\microsoft shared\web server extensions\12\bin especificando mediante –o la opción que deseamos y mediante los parámetros especificamos lo que requerimos. Específicamente –unique describe que no queremos heredar los permisos. Subrayo en rojo la parte donde especificamos el URL del sitio que estaremos creando. En este caso estamos creando un sitio llamado Sitio 1 y posteriormente creando cuatro grupos en donde los grupos Visitors y Members tienen como dueño al grupo Permissions.


stsadm.exe -o createweb –url “el url del sitio donde crearemos/url del nuevo sitio -lcid 1033 -sitetemplate STS#0  -title “Sitio 1″ -description “” –unique


stsadm.exe -o creategroup -url “el url del sitio donde aplicaremos” -name “Sitio 1 Permissions” -description “Permissions of the site” -ownerlogin “administrator@litwareinc.com” -type “Owner”


stsadm.exe -o creategroup -url “el url del sitio donde aplicaremos” -name “Sitio 1 Owners” -description “Owners of the site” -ownerlogin “administrator@litwareinc.com” -type “Owner”


stsadm.exe -o creategroup -url “el url del sitio donde aplicaremos” -name “Sitio 1 Visitors” -description “Visitors of the site” -ownerlogin “Sitio 1 Permissions” -type “Visitor”


stsadm.exe -o creategroup -url “el url del sitio donde aplicaremos” -name “Sitio 1 Members” -description “Members of the site” -ownerlogin “Sitio 1 Permissions” -type “Member”


 


Personalmente en ocasiones he llegado a pensar, ¿qué es mas complejo?, la tecnología o la psicología, en fin.


¿Cuál es la mejor alternativa? Depende Sonrisa

WSS 3.0 del primo de un amigo

El primo de un amigo comenta que su implementación de WSS 3.0 con SP2 después de 2 o 3 semanas de implementarse en producción muestra comportamiento muy extraño. Sucede que el disco duro del servidor de aplicaciones se ha llenado de forma repentina y sin explicación alguna.

La realidad es que si existen dos explicaciones.

  • La primera es que la implementación WSS 3.0 con SP2 del primo de un amigo careció de planeación y gobernabilidad.
  • La segunda es que la bitácora de rastreo a.k.a trace log ha saturado con archivos e información de trace  el disco duro.

Sucede que WSS 3.0 recién instalado fuera de la caja viene con la configuración de trace log automática de generar 100 archivos de log durante 100 minutos. Si hacemos la matemática de esto podríamos fácilmente identificar porqué se llenó el disco duro estrepitosamente.

La solución es hacerle caso a la herramienta central de administración y en la sección de OperationsDiagnostic logging dar clic al enlace “Learn about using trace log” para entender realmente las implicaciones de especificar el número de archivos de logs que SharePoint va a generar durante un periodo de minutos por archivo, con la finalidad de consolidar en una bitácora informacion de cambios que le permita al administrador de la granja entender comportamientos de procesos y configuracion.

image

Un saludo al primo de mi amigo que se llama Juan para que me entiendas Pedro. Smile

Explorando el uso de autentificación basada en formularios en SharePoint 2007

Autentificación basada en formularios es una propuesta decente para implementar el manejo de credenciales en aplicaciones .NET, no es la propuesta definitiva ya que no utiliza estándar alguna sin embargo si da soluciones para los escenarios propietarios de gestión de credenciales. En SharePoint 2010 se sigue soportando y justamente se ha implementado seguridad basada en demanda como la propuesta estandar. Siguendo con el tema, debido a que SharePoint 2007 fue construido sobre ASP.NET 2.0 el uso y configuración de Membership Providers es soportado permitiéndonos poder implementar diferentes mecanismos y escenarios de autentificación para hacer realidad nuestro requerimientos.

Si tienes la necesidad o el requerimiento de implementar o construir tu propia implementación de Membership Provider para usarla en SharePoint aquí dejo un articulo que me parece lo suficientemente completo para lograrlo.

Suerte con eso!

HG

tan simple y tan complicado a la vez

Ya en el pasado había platicado sobre el valor que aporta Rights Management Services de Microsoft a las organizaciones. Hoy definitivamente quiero puntualizar algunos asuntos técnicos a considerar cuando intentamos integrar RMS con SharePoint 2007.

  • No olvides instalar sobre los Web Front End de tu granja SharePoint el cliente de RMS SP2, este nos agrega un conjunto de entradas en el registro de Windows que SharePoint usa para poder preguntar por los permisos de un usuario en particular, si  no lo instalas SharePoint no tendrá manera de conectarse a tu servidor RMS
  • En el servidor RMS que se asume esta en otro equipo dentro de la granja hay que configurar permisos para las cuentas de la granja y del application pool del Shared Service Provider así como también al grupo local RMS Service Group en el archivo c:\inetpub\wwwroot\_wmcs\Certification\ServerCertification.asmx
  • Si recibes el error “You do not have permission to sub-enroll to the root server ‘http://xxx/_wmcs/Certification/SubEnrollService.asmx’. Contact your system administrator.” Mientras aprovisionas tu servidor RMS es porque seguramente en algún lugar de tu empresa ya se cuenta con otro servidor RMS instalado, asegúrate de averiguar donde esta, si se usa y si lo puedes desinstalar.
  • En caso de que desinstales algún servidor RMS deberás de ir a los servicios del directorio activo a eliminar una entrada que contiene los datos generales de tu conexión anterior. EL lugar exacto es  Directorio Activo – Consola de Sitios y Servicios – View – Show Services Node. Por ahí debe de estar el nodo WindowsRightsManagement y deberás eliminarlo, después procederás a configurar el nuevo desde la herramienta de configuración RMS.

Suerte!