OwnerEventHandler 1.0.0

Recientemente he publicado en codeplex el proyecto “OwnerEventHandler”. Consiste en una solución sharepoint que despliega un eventhandler para controlar las modifiocaciones de los elementos o documentos.

OwnerEventHandler permite que los usuarios tenga permisos de colaborador en las listas o librerías pero solo puedan modificar o editar los documentos de los que son propietarios.

La ventaja de este proyecto es que tiene múltiples utilidades con ciertos cambios en el código. Por ejemplo: podríamos utilizarlo para cambiar los permisos de los elementos, de manera que cada usuario pudiera ver los elementos que haya subido, o incluso podrías hacer que solo los pudieran editar un grupo de usuarios encargados de la supervisión.

El proyecto está compuesto de una solución WSP “OwnerEventReceiver”, que contiene una feature a nivel de sitio “OwnerItemEventReceiver”. El eventHandler está alojado en la librería OwnerEventHandler.dll.

Para registrarlo en una librería o biblioteca podemos utilizar "Event handler explorer”.

El código es bastante sencillo, consiste en un EventHandler que captura el evento ItemAdded para modificar los permisos de manera que todos los miembros excepto el propietario tengan permisos de lectura.

 

public class OwnerEventItemEventReceiver : SPItemEventReceiver
    { 
         public override void ItemAdded(SPItemEventProperties properties)
        {
            try
            {
                SPUser currentUser = properties.ListItem.ParentList.ParentWeb.CurrentUser;

                using (SPWeb webOrigUser = properties.OpenWeb())
                {
                    SPUserToken token = webOrigUser.AllUsers["SHAREPOINT\system"].UserToken;
                    using (SPSite site = new SPSite(properties.SiteId, token))
                    {
                        using (SPWeb currentWeb = site.OpenWeb(properties.RelativeWebUrl))
                        {

                            try
                            {
                                DisableEventFiring();

                                SPList sourceList = currentWeb.Lists[properties.ListId];
                                SPListItem itemAdded = sourceList.GetItemById(properties.ListItem.ID);
                                if (!itemAdded.HasUniqueRoleAssignments)
                                {
                                    itemAdded.BreakRoleInheritance(true);
                                    itemAdded.ParentList.ParentWeb.Dispose();
                                }

                                SPRoleAssignmentCollection roleAssignmentCollection = itemAdded.RoleAssignments;
                                foreach (SPRoleAssignment roleAssignment in roleAssignmentCollection)
                                {
                                    roleAssignment.RoleDefinitionBindings.RemoveAll();
                                    roleAssignment.RoleDefinitionBindings.Add(currentWeb.RoleDefinitions.GetByType(SPRoleType.Reader));
                                    roleAssignment.Update();
                                }

                                SPRoleDefinition reviserRoleDefinition = currentWeb.RoleDefinitions.GetByType(SPRoleType.Administrator);
                                SPRoleAssignment reviserRolePropietario = new SPRoleAssignment(currentUser);
                                reviserRolePropietario.RoleDefinitionBindings.Add(reviserRoleDefinition);
                                itemAdded.RoleAssignments.Add(reviserRolePropietario);

                                itemAdded.Update();
                            }
                            catch (Exception ex1)
                            {
                                properties.ErrorMessage = ex1.Message;
                                properties.Status = SPEventReceiverStatus.CancelWithError;
                                System.Diagnostics.Trace.Write("Exception OwnerEventHandler.OwnerEventItemEventReceiver.ItemAdded.1: {0}", ex1.Message);
                            }
                            finally
                            {
                                EnableEventFiring();
                            }

                        }
                    }
                }
            }
            catch (Exception ex)
            {
                properties.ErrorMessage = ex.Message;
                properties.Status = SPEventReceiverStatus.CancelWithError;
                System.Diagnostics.Trace.Write("Exception OwnerEventHandler.OwnerEventItemEventReceiver.ItemAdded: {0}", ex.Message);
            }
        }

    }

 

Lo primero que hacemos es obtener el token del usuario system, esto es parecido a ejecutar “SPSecurity.RunWithElevatedPrivileges”.

A continuación abrimos una referencia a la colección y al sitio, hacemos esto en lugar de utilizar el del SPItemEventProperties debido a que las referencias que mantiene el elemento añadido referencian al usuario que añadió el elemento, por lo que a la hora de modificar los permisos puede que no tenga permisos de Adminsitrador.

Después recorremos todas las configuraciones de permisos del elemento añadido y las editamos de manera que los miembros solo puedan leer.

Por último añadimos al usuario propietario el control total sobre el elemento.

¿Cumpliste los objetivos?

Es lo que toca este mes, revisar objetivos. Este año parece que mucha gente no los está cumpliendo o si los cumple da igual, porque no hay dinero. ¿Pero no se supone que los objetivos son acerca de como lo hayas hecho el 2008?. ¿Para que sirven los objetivos o pagas de beneficios y demás?.

A mi entender los objetivos deben plantearse como un aliciente para que los empleados se involucren más en la compañía y para que tanto empresa como empleado evolucionen en el mismo camino, “Yo te ayudo, pero tú me ayudas a mí”. Evidentemente si lo haces bien deberías merecerte una subida de sueldo o un incentivo, pero es que el trabajo deberíamos hacerlo siempre bien, el cliente siempre debería estar contento con nosotros. Por lo tanto los objetivos deben ir más allá, deben de promover actitudes y actividades que hagan que el empleado y la empresa sean diferenciales del resto.

En mi caso no he cumplido objetivos porque me lo propuse así desde el principio, en mi caso estaban mal planteados. Es decir se daba importancia a aspectos que deberíamos tener y se premiaban actividades que realmente no aportaban mucho a la empresa y al resto de compañeros.

Al menos este año en nuestra empresa parece que se han dado cuenta y lo han intentado solucionar para 2009. Aparte de las certificaciones, se valoran aspectos como dar charlas o gravarlas (antes no valía con grabarlas!!), dar cursos, workshops o similares, mantener un blog (esta la tengo asegurada). En resumen, este 2009 habrá que arrimar el hombro para ayudar a nuestra empresa a ser más atractivos.

¿y tú qué tal este año?.

Documentación Microsoft Dynamics NAV 2009

Microsoft ha publicado varias guías para el desarrollo, instalación y administración de Nav2009. podéis descargarlo en “Microsoft Dynamics NAV 2009 Developer and IT Pro Help”.

Os recomiendo algunos post como: “Microsoft Dynamics NAV Team Blog”, “Clausl’s Dynamics NAV Blog”, “Freddys Blog”, “Waldo’s blog”, “Kine’s blog

This Page has been modified since you opened it

El webpart que estaba construyendo estaba extendiendo las funcionalidades de búsqueda de MOSS y al hacer un submit a la página de resultado me daba el error “This Page has been modified since you opened it. You must open the page again.” o “Se ha modificado esta página desde que la abrió. Debe volver a abrirla.”. Lo curioso es que encima no dejaba ninguna marca en el log de Sharepoint ni de windows, por lo que no sabes exactamente que está pasando.

image

 

Al final después de mucho batallar, me fijé que el control estándar que estaba extendiendo llamaba a dos funciones javascript al hacer el submit

… onclick="ResetPageHashCode();WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions( …

Al principio no le dí mucha importancia, pero justo cuando estaba probando con Fidler para ver comparar lo que enviaba el control estándar con el mío, me di cuenta que borrando el valor del parámetro post “MSO_PageHashCode” dejaba de dar el error. Qué curioso!!!, resulta que mirando el código de la función “ResetPageHashCode” borra este elemento de la página antes de hacer un submit.

Efectivamente añadiendo esta llamada antes de hacer un submit conseguí arreglar mi control, aunque en mi caso tuve que tocarla ya que no me llegaba a funcionar del todo:

function ResetPageHashCode()
    {
        var f = document.forms[0];
        if (null != f && null != f.elements[‘MSO_PageHashCode’])
           f.elements[‘MSO_PageHashCode’].value = "";

        _spFormOnSubmitCalled = false;
    }

 

<asp:Button ID="ASB_BS_SRCH_1" runat="server" Text="Buscar" CssClass="boton" OnClientClick="ResetPageHashCode();Buscar();" />

 

No puedo asegurar que sea la solución para todos los casos en los que ocurre este error ya que se proponen muchas soluciones, pero en mi caso ha funcionado.

Otras soluciones a este error:

Resolution: MOSS: This Page has been modified since you opened it. You must open the page again.

SharePoint Errors, Warnings and Problems Collection 

This Page has been modified since you opened it. You must open the page again.

Finally: A Federation Search results page that doesn’t give me the need to "Refresh Page" before I can see the results

Novedades en Windows SharePoint Services 4.0?

Recientemente Michael Greth ha publicado dos post donde nos comenta algunas de las novedades que incorporará WSS 4.

Custom List Views and WSS 4.0’s XSLT-based List View

Custom Field Types and WSS 4.0’s XSLT-based Field Type

 

Según comenta Michael Greth, Microsoft ha publicado varios artículos (The CustomListView rule in Pre-Upgrade Checker can warn that customized list views that will not be upgraded y La regla CustomFieldType en Comprobador previas a la actualización en el Service Pack 2 de Windows SharePoint Services 3.0 puede advertir que campo personalizado no se actualizarán tipos) acerca de posibles errores con los list view y algunos customfields al actualizar a la nueva versión de Sharepoint Service.

De estos artículos Michael saca las siguientes conclusiones acerca de la siguiente versión WSS 4:

  • El List View WebPart evoluciona a una nueva versión XSLT-based List View Web Part con nuevas funcionalidades como la mejora en la personalización con Sharepoint Designer, formatos condicionales y mejoras en la experiencia del desarrollo con XSLT.
  • Aparecerá un nuevo tipo de campo llamada XSLT-based field type.

 

Bueno, veremos que pasa en estos meses que llegan, lo que si es seguro es que todos estamos deseando tener en nuestras manos la nueva versión.