SharePoint 2013 y los eventos remotos

Una de las tareas más comunes que nos solicitan como desarrolladores de SharePoint es la de programar actividades a realizarse para responder ante algún evento (receptor de eventos), como enviar un correo electrónico al agregarse un nuevo documento a una biblioteca de documentos. Con la aparición de las aplicaciones para SharePoint (ahora SharePoint Add-in) también apareció el concepto de Receptores de Eventos Remotos (Remote Event Receivers) que no es más que una respuesta a un evento pero, con código fuera de SharePoint, es decir, en un entorno aislado en el cuál sólo se puede interactuar con SharePoint mediante las interfaces previsto para ello.

¿Pero cuál es el problema? Bien, una de las cosas que he notado (y que me han ocurrido también) es que cuando se está depurando en ocasiones el código no se ejecuta y nos quedamos preguntándonos qué sucede, la respuesta puede ser sencilla, cada vez que compilamos la aplicación se genera un nuevo Guid para la aplicación y si por alguna causa el Evento no se desasoció correctamente, nos encontramos que la nueva definición del evento (con el nuevo Id de aplicación) no se añade y SharePoint continuará intentando activar la llamada utilizando la aplicación «antigua» (la aplicación con el Guid anterior).

¿Y cómo soluciono el problema? Bien, digamos que si estamos trabajando en un ambiente «on-premise» es relativamente sencillo, bastará con obtener el objeto al que está asociado el receptor de eventos vía SharePoint 2013 Management Shell y lo eliminamos, algo como el siguiente ejemplo:

#Obtener el objeto Web
$web = Get-SPWeb <<URL>>
$Obtener la lista
$list = $web.Lists[<<título de la lista>>]
#Mostrar los eventos
$list.EventReceivers
#Ubica y cuenta en qué posición se encuentra el ER que quieres eliminar.
$list.EventReceivers[<<Posición menos 1>>].Delete()#Recuerda que la posición se cuenta desde cero (0)

Si deseas eliminar todos los ERs del objeto es mucho más simple realizar lo siguiente:

#Obtener el objeto Web
$web = Get-SPWeb <<URL>>
$Obtener la lista
$list = $web.Lists[<<título de la lista>>]
#Eliminar los receptores de eventos
for($i = $list.EventReceivers.Count - 1; $i -ge 0; $i --)
{
    $list.EventReceivers[$i].Delete()
}

En el caso de SharePoint Online debemos utilizar CSOM para esto emplearemos una pequeña modificación:

#Agregar las DLLs necesarias para utilizar CSOM desde la consola, recuerda ajustar con la dirección de las DLLs
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll" 
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll" 
# note that you might need some other references (depending on what your script does) for example:
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Taxonomy.dll" 

$usr = <<usurio@dominio>>
$secPwd = ConvertTo-SecureString <<contraseña>> -AsPlainText -Force

$ctx = New-Object Microsoft.SharePoint.Client.ClientContext(<<url web>>) 
$cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($usr, $secPwd)
$ctx.Credentials = $cred

if (!$Context.ServerObjectIsNull.Value) 
{
    $list = $ctx.Web.Lists.GetByTitle($listName)
    $ctx.Load($list)
    $evtRcv = $list.EventReceivers
    $ctx.Load($evtRcv)
    $ctx.ExecuteQuery()

    for($i = $evtRev.Count - 1; $i -ge 0; $i--)
    {
        $evtRev[$i].DeleteObject()
    }
    $ctx.ExecuteQuery()
}

Finalmente si deseas un script mucho más desarrollado y con manejo de excepciones puedes visitar el blog de Chris O’Brien quien muestra un hermoso script para trabajar con CSOM y PowerShell.

NOTA: Todo el código suministrado en este post y en todo el sitio se provee «TAL CUAL» sin garantías de ningún tipo, ni explícitas ni implícitas y el usuario de dicho código es responsable de las consecuencias de hacer uso del mismo. Ni el autor de este post ni ningún otro autor de este sitio asumen ningún tipo de responsabilidad directa o indirecta por el uso del código.