El otro día nos encontramos frente a un requerimiento que nos solicito un cliente. El necesitaba listar los documentos más vistos de una colección de sitios y todos los sub sitios por debajo de dicha colección de sitio. Sharepoint posee una característica llamada “Auditoria de la información” la cual una vez habilitada y configurara en el sitio correspondiente registra todos los eventos que se producen en toda la colección de sitios. Se puede registrar los ítem vistos, los ítem modificados, etc. En definitiva se auditan todos los eventos que se producen en nuestro portal Sharepoint 2007, próximamente vamos a estar compartiendo con Uds. un artículo al respecto, dado que dicha característica es muy útil. Pero para este caso en particular nosotros tomamos la decisión de realizar un modulo que atrapara la URL del request y procesara si se trataba de un documento o de simplemente una página. Este modulo implementa la interface IHttpModule de Asp.Net, nos permite registrarnos a eventos durante todo el proceso de solicitud que se está realizando en nuestro portal Sharepoint 2007. Durante una solicitud (Request) a una página de nuestro portal durante todo el proceso del mismo se desencadenan varios eventos a los cuales nosotros nos podemos registrar. Estos eventos tienen un orden lo cual nos permite codificar algún comportamiento adicional en determinado momento. En la sección 1 vemos la lista de eventos proporcionada por la clase SPHttpApplication la cual usamos para registrarnos a los mismos. Cabe la pena destacar que dicha clase extiende de HttpApplication de Asp.Net e incorpora algunas propiedades y métodos adicionales, por mas información dirigirse a la pagina del MSDN.
Sección 1 · AcquireRequestState · AuthenticateRequest · AuthorizeRequest · BeginRequest · Disposed · EndRequest · Error · PostAcquireRequestState · PostAuthenticateRequest · PostAuthorizeRequest · PostMapRequestHandler · PostReleaseRequestState · PostRequestHandlerExecute · PostResolveRequestCache · PostUpdateRequestCache · PreRequestHandlerExecute · PreSendRequestContent · PreSendRequestHeaders · ReleaseRequestState · ResolveRequestCache · UpdateRequestCache
Vale la pena destacar que si queremos acceder al modelo de objeto del portal en ejecución mediante la clase SPContext nos deberíamos registrar a cualquier evento después del evento “PostAuthenticateRequest” dado que recién después del mismo estamos autenticándoos y tendremos acceso al contexto de ejecución. En la sección 2 vemos el código necesario para la creación de nuestro HttpModule utilizando Visual Studio 2005 y en el cual nos registramos a dos eventos “BeginRequest” y “PostRequestHandlerExecute”. En el primero no contamos con acceso al contexto de ejecución, si quisiéramos acceder a al sitio en ejecución obtendríamos un error indicando que el objeto no está listo, pero sí en cambio lo hacemos en el segundo evento, como el proceso de autorización se produjo no tendremos problema en acceder al sito en ejecución.
Sección 2
using System; using System.Collections.Generic; using System.Text; using System.Web; using Microsoft.SharePoint; using Microsoft.SharePoint.ApplicationRuntime;
namespace Siderys.HttpModuleBlog { public class HttpModuleSharepoint : IHttpModule { public void Init(HttpApplication app) { SPHttpApplication spApp = (SPHttpApplication)app; spApp.BeginRequest += new EventHandler(BeginRequestHttpModuleBlog); spApp.PreRequestHandlerExecute += new EventHandler(PreRequestHandlerExecuteHttpModuleBlog); }
void BeginRequestHttpModuleBlog(object sender, EventArgs e) { HttpContext.Current.Response.Write("HttModuleBlog <br>"); } public void PreRequestHandlerExecuteHttpModuleBlog(object sender, EventArgs e) { HttpContext.Current.Response.Write(SPContext.Current.Web.ToString()); } public void Dispose() { }
} }
Una vez tenemos programado nuestro HttpModule, lo que resta es registrarlo en el WebConfig del portal de Sharepoint, realizar un IISRESET para que el nuevo Assembly sea tenido en cuenta y realizar una petición al portal para que se ejecute nuestro HttpModule. En la sección 3 vemos el código necesario para agregar al Web.Config de nuestro portal Sharepoint.
Sección 3 <httpModules> <clear /> . De más modulos <add name="HttpModuleBlog" type="Siderys.HttpModuleBlog.HttpModuleSharepoint, Siderys.HttpModuleBlog, Version=1.0.0.0, Culture=neutral, PublicKeyToken=4b47d67002a80c61" /> </httpModules> En la imagen 1 vemos como lo que nosotros codificamos en el en el HttpModule se muestra en la pagina solicitada. Es simplemente un ejemplo de lo que podemos realizar para solucionar algunos requerimientos.
Imagen 1
|
Mes: enero 2008
WebPart para Sharepoint 2007 usando UserControl
En el artículo anterior explicamos cómo usar el control de Sharepoint 2007 PeopleEditor y desarrollamos un formulario para colocarlo en Sharepoint. En realidad lo que construimos fue una WebPart utilizando un UserControl la cual registramos en nuestro Sharepoint y utilizamos. Cuando necesitamos agregar funcionalidad adicional a nuestros sitios de Sharepoint recurrimos a la codificación mediante WebParts, las cuales nos permiten desarrollar dicho componente e incluirlo en nuestro portal Sharepoint. Pero todo sabemos que la codificación de una WebPart no es trabajo fácil y más cuando nos tenemos que preocupar de todo el dibujo (renderización de los controles incluidos en la misma) y el manejo de los preciados eventos, cuando la WebPart es sencilla no es tan complicado su desarrollo, pero ahora si lo que debemos codificar es un formulario complejo, el desarrollo de la misma no es nada trivial. Nosotros vamos a desarrollar una WebPart, pero en vez de codificarla toda en la clase que implementa la clase base WebPart, lo vamos hacer mediante un UserControl de Asp.Net. Lo primero que tenemos que hacer es preparar nuestro ambiente en Visual Studio, para lo cual necesitamos 2 proyectos, un proyecto Web donde codificaremos el UserControl y un proyecto de Clases donde codificaremos nuestra WebPart, en la siguiente imagen se puede ver como quedaría nuestro ambiente: Imagen 1
Lo que debemos hacer ahora es configurar nuestros dos proyectos, para poder agregar la referencia al proyecto de biblioteca de clases. Ambos dos proyectos deben estar firmados con un Strong Name (archivo snk, si tienen uno en común para todos sus desarrollos pueden utilizarlo, si no pueden generar uno con el Visual Studio), el primer proyecto que vamos a configurar es la biblioteca de clases y en las propiedades del proyecto vamos a colocar en archivo snk (Strong Name) en la sección correspondiente a firma del Visual Studio, como se puede ver en la imagen siguiente:
Imagen 2
Por último en la clase AssemblyInfo vamos agregar una elevación en los permisos de ejecución de nuestra WebPart para que la misma se ejecute sin ningún problema en nuestro portal de Sharepoint 2007, para eso agregamos el siguiente atributo en nuestro AssemblyInfo [assembly: AllowPartiallyTrustedCallers()], en la siguiente imagen vemos como quedaría: Imagen 3
Una vez configurado nuestro proyecto de biblioteca, lo que demos hacer es configurar nuestro proyecto Web y crear el UserControl correspondiente, para lo cual vamos agregar un nuevo componente a dicho proyecto del tipo UserControl y lo vamos a grabar en el mismo. Una vez agregado lo que demos hacer es codificar el mismo según nuestras necesidades y requerimientos. En la imagen 4 vemos nuestro UserControl codificado, como nos estamos basando en el artículo anterior, nuestro UserControl simplente dibuja el control de Sharepoint PeopleEdito. Imagen 4 En la clase asociada a dicho UserControl vamos a codificar todo nuestro comportamiento para el mismo. Una vez que está terminado tenemos que publicarlo así podemos crear el Assembly necesario para dicho UserControl, para ello nos paramos sobre nuestro proyecto Web y seleccionamos publicar. En la nueva ventana que aparece en nuestro Visual Studio vamos a configurar como vamos hacer la publicación, debemos seleccionar una ruta donde se colocaran los archivos generados, vamos a indicarle que nos genere un Assembly independiente para cada uno de los archivos que tenemos en el proyecto Web y vamos a firmar los mismo con un Strong Name (el archivo snk a utilizar puede ser el mismo que utilizamos para firmar la biblioteca de clases), la imagen 5 nos muestra como quedaría la pantalla configurada. Imagen 5 Una vez publicado, vamos agregar la referencia al Assembly generado por el proceso de publicación en nuestro proyecto de clases, nuestro proyecto de clase debería quedar como se muestra en la siguiente imagen. Imagen 6 Los ultimo que vamos hacer es codificar nuestra WebPart para utilizar el UserControl utilizando el método LoadControl y pasándole una ruta a la ubicación de nuestro archivo ASCX, esta ruta deberá ser una ruta relativa en la raíz de nuestro portal Sharepoint, en nuestro caso colocamos el archivo ASCX en una carpeta llamada “UserControl” como se puede ver en la siguiente imagen. Imagen 7 En la siguiente sección entraremos el código necesario para cargar el UserControl en la WebPart y adicionarlo a la colección de controles. También hemos incorporado un manejo de errores que nos permitirá enviar el mensaje de error producido a la pantalla utilizada por Sharepoint 2007 para mostrar los mensajes de error.
Sección 1
using System; using System.Runtime.InteropServices; using System.Web.UI; using System.Web.UI.WebControls.WebParts; using System.Xml.Serialization; using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls; using Microsoft.SharePoint.WebPartPages; using Microsoft.SharePoint.Utilities;
namespace PeopleEditorWebControlWebPart { public class PeopleEditorWebControlWebPart : System.Web.UI.WebControls.WebParts.WebPart { private PeopleEditorWebControlUC mPeopleEditorWebControlUC = null; private Exception mError = null; private string mSourceQuery = string.Empty;
public PeopleEditorWebControlWebPart() { this.ExportMode = WebPartExportMode.All; } protected override void CreateChildControls() { try { base.CreateChildControls(); mPeopleEditorWebControlUC = (PeopleEditorWebControlUC)Page.LoadControl(@"/UserControl/PeopleEditorWebControlUC.ascx"); Controls.Add(mPeopleEditorWebControlUC); } catch (Exception ex) { mError = ex; } } protected override void Render(HtmlTextWriter writer) { if (mError != null) { SPUtility.TransferToErrorPage(mError.Message + " —> " + mError.StackTrace); } base.Render(writer); } } } |
Por último nos queda compilar nuestra WebPart y registrarla en nuestro portal de Sharepoint para poder utilizarla, como cualquier otra Webpart. |
Configuración Búsqueda Sharepoint 2007
Manejando las propiedades del motor de búsqueda de Sharepoint 2007.
|
||||||||||||||||||||||
|
|
Página resultado búsqueda Sharepoint 2007
WebControl PeopleEditor Property Webpart Sharepoint 2007
Estábamos desarrollando una WebPart, otro de los requerimientos solicitados por un cliente, cuando con Santiago, Javier y yo nos pusimos a discutir cómo podíamos desarrollarlo. Le empezamos a dar vuelta al tema y encontramos una solución, que se cargara un usuario en las propiedades de las la WebPart que estábamos desarrollando. Entonces decidimos colocar una simple propiedad para que se cargara el usuario que necesitábamos y el usuario final simplemente debía escribir el nombre de un usuario para ser configurado. Pero Santiago fue más lejos y se puso a investigar cómo se podría utilizar el control de Sharepoint 2007 PeopleEditor para brindar al usuario una forma natural de configurar un usuario en nuestra WebPart. Las WebParts pueden sobre escribir (override) el método GetToolParts() que devuelve un Array del objeto ToolPart. En este Array vamos a retornar las instancias de dos clases “WebPartToolPart – CustomPropertyToolPart” del espacio de nombre “Microsoft.SharePoint.WebPartPages” y la instancia de una clase personalizada que nosotros vamos a crear y que extiende de la clase “ToolPart” que se encuentra en el espacio de nombre ”Microsoft.SharePoint.WebPartPages”. Lo primero que tenemos que hacer es crear nuestra WebPart, la misma debe heredar de la clase WebPart de Sharepoint, esta clase se encuentra en el espacio se nombre “Microsoft.SharePoint.WebPartPages” puesto que esta clase es la que contiene el método que debemos sobre escribir (override) GetTollParts() y la clase WebPart de Asp.Net no implementa dicho metodo. En la sección 1 vemos la implementación de nuestra WebPart la cual es una WebPart simple que lo que hace es mostrar los datos del usuario configurado en el control PeopleEditor.
Sección 1
using System; using System.Runtime.InteropServices; using System.Web.UI; using System.Web.UI.WebControls.WebParts; using System.Xml.Serialization; using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls; using Microsoft.SharePoint.WebPartPages; using System.ComponentModel; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls;
namespace Siderys.Blogs.WebPart { [Guid("b604193b-be0f-4b2e-8b82-d9783fe8c262")] public class PeopleEditorWebpart : Microsoft.SharePoint.WebPartPages.WebPart { private SPUser mUsuario = null; public PeopleEditorWebpart() { this.ExportMode = WebPartExportMode.All; } [Browsable(false)] public SPUser Usuario { get { return mUsuario; } set { mUsuario = value; } } protected override void Render(HtmlTextWriter writer) { HtmlTable lTable = new HtmlTable(); HtmlTableRow lRow = new HtmlTableRow(); HtmlTableCell lCell = new HtmlTableCell(); if (mUsuario != null) { //Nombre lCell.InnerText = "Nombre: "; lRow.Controls.Add(lCell); lCell = new HtmlTableCell(); lCell.InnerText = mUsuario.Name; lRow.Controls.Add(lCell); lTable.Controls.Add(lRow); //Es admin lCell = new HtmlTableCell(); lRow = new HtmlTableRow(); lCell.InnerText = "Es Admin: "; lRow.Controls.Add(lCell); lCell = new HtmlTableCell(); lCell.InnerText = mUsuario.IsSiteAdmin.ToString(); lRow.Controls.Add(lCell); lTable.Controls.Add(lRow); } else { lCell.InnerText = "No hay usuario seleccionado"; lRow.Controls.Add(lCell); lTable.Controls.Add(lRow); } lTable.RenderControl(writer); } public override ToolPart[] GetToolParts() { ToolPart[] lToolPart = new ToolPart[3]; WebPartToolPart lWebPartToolPart = new WebPartToolPart(); CustomPropertyToolPart lCustomToolPart = new CustomPropertyToolPart(); lToolPart[0] = lCustomToolPart; lToolPart[1] = lWebPartToolPart; lToolPart[2] = new ToolPartPeopleEditor(); return lToolPart; } } }
Bien ahora vamos a implementar la clase “ToolPartPeopleEditor” que utilizamos en el método GetToolParts() la cual es la que crea una instancia del control PeopleEditor y la carga en el panel de configuración de la WebPart. En la sección 2 vemos la implementación de la clase mencionada. Esta clase realiza la sobre escritura (override) de los métodos “RenderToolPart”, “CreateChildControls” y “ApplyChanges”. El primer método dibuja el contenido de la clase, el segundo método agrega la instancia del control PeopleEditor creado en el evento “Init” y el último método es utilizado para obtener el valor del control cargado cuando el usuario presiona el botón “Apply”.
Sección 2
using System; using System.Collections.Generic; using System.Text; using Microsoft.SharePoint.WebControls;
namespace Siderys.Blogs.WebPart { public class ToolPartPeopleEditor : Microsoft.SharePoint.WebPartPages.ToolPart { private PeopleEditor lPeopleEditor = null; private const string lNombreControl = "ctl00$MSOTlPn_EditorZone$Edit2g_71a9f59a_11e8_4672_8953_8b96927aee44$PeopleEditorWebPart$downlevelTextBox"; public ToolPartPeopleEditor() { Title = "Seleccionar Usuario ToolPart"; Init += new EventHandler(ToolPartPeopleEditor_Init); }
void ToolPartPeopleEditor_Init(object sender, EventArgs e) { lPeopleEditor = new PeopleEditor(); lPeopleEditor.ID = "PeopleEditorWebPart"; lPeopleEditor.AllowEmpty = false; lPeopleEditor.ValidatorEnabled = true; lPeopleEditor.MultiSelect = false; lPeopleEditor.SelectionSet = PeopleEditor.AccountType.User.ToString(); } public override void ApplyChanges() { PeopleEditorWebpart lPeopleWebPart = (PeopleEditorWebpart)ParentToolPane.SelectedWebPart; string lUsuarioCargado = Page.Request.Form[lNombreControl].ToString(); lPeopleWebPart.Usuario = Microsoft.SharePoint.SPContext.Current.Web.AllUsers[lUsuarioCargado]; } protected override void RenderToolPart(System.Web.UI.HtmlTextWriter output) { output.Write("<BR/>"); base.RenderToolPart(output); } protected override void CreateChildControls() { base.CreateChildControls(); Controls.Add(lPeopleEditor); } } }
Una vez implementado estas dos clases lo que debemos hacer es compilar e instalar la WebPart en nuestro portal de Sharepoint. En la imagen 1 vemos como configuramos el control en el panel de propiedades de la WebPart y en la imagen 2 vemos como obtenemos el usuario cargado y mostramos algunos de sus valores.
Imagen 1 Imagen 2 En un próximo artículo vamos a seguir hablando de cómo podemos ir agregando funcionalidades a nuestras WebParts con controles de Sharepoint 2007. |
Como usar el control PeopleEditor de Sharepoint 2007
El otro día (vaya a saber uno que día), uno de esos días donde pasamos inmersos frente a la pantalla de nuestra computadora y las agujas del reloj dan vueltas como locas sin parar, me encontré frente a un requerimiento (uno de los tantos que tenia este desarrollo) y que teníamos que resolver. Con Javier veníamos dando dura batalla a todo lo que teníamos que desarrollar, él mano a mano con el WorkFlow y yo mano a mano con los formularios personalizados de las listas. En un momento tuvimos que cambiar el enfoque del desarrollo y salirnos de Infopath 2007 y volcarnos al desarrollo tradicional de WebParts. Otra vez nos encontramos con que Infopath 2007 para Forms Services está limitado y hay cosas que no se pueden hacer (ese es un tema aparte) y desarrollar un formulario utilizando una WebPart para dar de altas elementos en la lista. Una de las cosas que tenía que tener el formulario era la posibilidad de seleccionar usuarios de Sharepoint y cargarlos. Todos hemos trabajados con los formularios que nos proporciona Sharepoint 2007 para las listas. Cuando tenemos un campo del tipo Persona o Grupo, en el formulario se nos brinda un control que nos permite introducir dicho usuario o grupo, validarlo o desplegar una pantalla para buscarlo, en la siguiente imagen se muestra dicho control. Imagen 1
Estamos acostumbrados a utilizar este tipo de campos en los formularios de Sharepoint 2007 para cargar personas o grupos. Incluso Infopath 2007 provee un control Activex, Contact Selector para utilizar dicha características en los formularios creados, acá les dejo las dirección a dos artículos de amigos de la comunidad que explican al pie de la letra como utilizar dicho control, · Marco Nosotros queríamos mantener esta característica en los formularios que estábamos creando, así que decidimos utilizar el control PeopleEditor que nos provee Sharepoint 2007 para incorporarlo en los mismos. Sección 1 <%@ Register tagprefix="SharePoint" namespace="Microsoft.SharePoint.WebControls" assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> Una vez registrado el Assembly correspondiente estábamos en condiciones de poder usar el control en nuestro formulario, así que declarativamente lo incorporamos al mismo como se puede ver en la sección 2. Sección 2 <SharePoint:PeopleEditor ID="PeopleEditorPersona" AllowEmpty="false" ValidatorEnabled="true" MultiSelect="false" runat="server" SelectionSet="User" CssClass="general_control" />
En la sección 3 vemos algunas de las propiedades que podemos establecer en el control PeopleEditor.
Sección 3 · AllowEmpy: propiedad que indica si el control puede estar vacio. · ValidatorEnabled: propiedad que indica si la velicación esta activada. · MultiSelect: propiedad que indica si podemos selecciona más de un usuario a la vez. · SelectionSet: propiedad que indica que tipo de objeto podemos seleccionar, en nuestro caso, solo usuarios.
Todos los valores permitidos por la propiedad SelectionSet del control se encuentran listados en la siguiente enumeración dentro de la clase PeopleEditor:
Microsoft.SharePoint.WebControls.PeopleEditor.AccountType
Para más información de esta enumeración vistitar la pagina del MSDN
Una vez el control está cargado en nuestro formulario lo que debemos hacer es colocar el código necesario para poder tomar los usuarios ingresados en el mismo. En nuestra clase asociada al control ASCX nos referimos al control utilizando la propiedad ID y utilizando la propiedad “Accounts” la cual nos brinda colección de strings con los usuarios cargados en el formato “dominiousuario”. Con cada elemento de la posición del ArrayList podemos cargar el usuario del sitio Web para tomar sus valores, en la sección 4 vemos el código completo del método asociado al evento click de nuestro botón “Guardar” del formulario y un método adicional que obtiene el usuario de nuestro portal Sharepoint 2007 a partir de la cuenta cargada. Para obtener el usuario del portal utilizamos el objeto SPContext que nos brinda una referencia al contexto de ejecución del sitio actual. Sección 4 protected void cmdGuardar_Click(object sender, EventArgs e) { SPUser lUser = GetUserLogged(PeopleEditorPersona.Accounts[0].ToString()); lblMsg.Text += "Nombre: " + lUser.Name + "<br>"; lblMsg.Text += "Login Name: " + lUser.LoginName + "<br>"; lblMsg.Text += "Email: " + lUser.Email + "<br>"; } private SPUser GetUserLogged(string pUserAccount) { return SPContext.Current.Web.AllUsers[pUserAccount]; }
En la magen 2 vemos como funciona el control dentro del formulario personalizdo creado para cargar el usuario de Sharepoint.
Imagen 2
|