使用 SharePoint 中的远程事件接收器

使用远程事件接收器处理 SharePoint 外接程序模型中的事件。 使用 AppInstalled 和 AppUninstalling 事件来设置或删除 SharePoint 对象和外接程序所需的其他事件接收器。

适用于:SharePoint 加载项 | SharePoint 2013 | SharePoint Online

重要说明:自 2017 年 1 月起,SharePoint Online 支持列表 Webhook,可用于取代过去的远程事件接收器。 若要详细了解 Webhook,请参阅 SharePoint Webhook 概述。 另请注意,还可以从 sp-dev-samples GitHub 存储库中获取多个 Webhook 示例。

Core.EventReceivers 示例说明如何使用带有远程事件接收器的提供程序托管的外接程序来处理 AppInstalled 和 AppUninstalling 事件。 AppInstalled 和 AppUninstalling 事件设置和删除此外接程序运行时所使用的 SharePoint 对象。 此外,AppInstalled 事件处理程序还将 ItemAdded 事件处理程序添加到列表。 如果你需要执行以下操作,请使用此解决方案:

  • 使用 AppInstalled 事件设置与您的外接程序配合使用的各种 SharePoint 对象或其他事件接收器,以便在首次运行外接程序时进行配置。
  • 使用完全信任的代码解决方案替换实现的事件接收器。 在完全信任的代码解决方案中,您可以在 SharePoint 服务器上运行事件接收器。 在新的 SharePoint 外接程序模型中,由于无法在 SharePoint 服务器上运行事件接收器,因此需要在 Web 服务器上实现远程事件接收器。
  • 接收 SharePoint 中发生更改的通知。 例如,在新项目被添加到某个列表时,您想要执行一个任务。
  • 补充您的更改日志解决方案。 使用带有更改日志模式的远程事件接收器提供更为可靠的体系结构,以便处理对 SharePoint 内容数据库、网站集、网站或列表所做的所有更改。 远程事件接收器立即运行,但是因为它们在远程服务器上运行,您可能会遇到通信故障。 更改日志模式确保所有更改都可供处理,但处理更改的应用(例如,计时器作业)通常是定期运行。 也就是说,不会立即处理更改。 如果同时使用这两种模式,请确保您使用某种机制来防止对同一更改处理两次。 有关详细信息,请参阅 使用 ChangeQuery 和 ChangeToken 查询 SharePoint 更改日志

注意

SharePoint 托管的加载项不支持远程事件接收器。 若要使用此接收器,你需要使用提供程序托管的外接程序。 对于同步方案或长时间运行的进程,您不应使用远程事件接收器。 有关详细信息,请参阅 如何:创建外接程序事件接收器

开始之前

若要开始,请从 GitHub 上的 Office 365 开发人员模式和做法项目下载 Core.EventReceivers 示例外接程序。

在运行此外接程序之前,请执行以下操作:

  1. 在 Core.EventReceivers 项目的属性中,验证 “处理应用已安装 ”和 “处理应用卸载” 是否设置为 True。 将 “处理已安装的应用 ”和 “处理应用卸载” 设置为 True 会创建一个 WCF 服务,该服务定义 AppInstalledAppUninstalling 事件的事件处理程序。 在 Core.EventReceivers 中,打开 AppManifest.xml 上的快捷菜单(右键单击),并选择“属性”InstalledEventEndpointUninstallingEventEndpoint 指向处理 AppInstalledAppUninstalling 事件的远程事件接收器。

  2. 将远程事件接收器附加到主机 Web 中的对象通常只需要该对象的 管理 权限。 For example, when attaching an event receiver to an existing list, the add-in requires Manage permission on the List only. This code sample requires Manage permissions on the Web because it adds a list and activates a feature on the host web. To set manage permissions on the web:

    1. 双击 Core.EventReceivers\AppManifest.xml。

    2. 选择“权限”

    3. 确认“作用域”设置为“Web”,且“权限”设置为“管理”

  3. 若要运行此代码示例,您需要一个 Azure 订阅。 若要注册试用版,请参阅 免费试用一个月

  4. 创建 Azure 服务总线命名空间。

    1. 按照创建服务总线命名空间中的说明操作。

    2. 从刚刚创建的服务总线命名空间中复制主要连接字符串

    3. 返回到 Visual Studio。

    4. 右键单击“Core.EventReceivers >属性>SharePoint”。

    5. 选择“通过 Microsoft Azure 服务总线启用调试”

    6. “Microsoft Azure 服务总线连接字符串”中,粘贴“连接字符串”。

    7. 选择“保存”。

  5. 运行此代码示例,并执行下面的其他步骤:

    • 在“向应用授予权限”窗口中单击“信任它”。

    • 关闭“ 向应用授予权限” 窗口。

    • 完成此外接程序和 WCF 服务的安装后,您的浏览器将会打开。

    • 登录到您的 Office 365 网站。 将显示 Core.EventReceivers 外接程序的起始页。

使用 Core.EventReceivers 外接程序

若要查看 Core.EventReceivers 代码示例的演示,请执行以下操作:

  1. 运行此示例,并在起始页上选择“返回到网站”

  2. 选择“网站内容”

  3. 选择“远程事件接收器作业”

  4. 单击“新建项目”

  5. 在“标题”中,输入 Contoso,并在“说明”中输入 Contoso 测试

  6. 返回到列表并刷新页面。

  7. 确认新添加的项目的说明已更新为由 ReR 192336 更新的 Contoso 测试,其中“192336”是时间戳。

在 Services/AppEventReceiver.cs 中,AppEventReceiver 实现 IRemoteEventService 接口。 此代码示例可以实现 ProcessEvent 方法,因为它使用同步事件。 如果您使用异步事件,则需要实现 ProcessOneWayEvent 方法。

ProcessEvent 处理以下 SPRemoteEventType 远程事件:

  • 安装外接程序时发生的 AppInstalled 事件。 发生 AppInstalled 事件时, ProcessEvent 调用 HandleAppInstalled

  • AppUninstalling events when uninstalling the add-in. When an AppUninstalling event occurs, ProcessEvent calls HandleAppUninstalling. AppUninstalling 事件仅在用户完全删除加载项时运行,方法是从网站回收站中删除加载项, (最终用户) ,或者从面向开发人员) 的测试列表中的应用中删除加载项 (。

  • 将某个项目添加到列表时发生的 ItemAdded 事件。 在发生 ItemAdded 事件时, ProcessEvent 调用 HandleItemAdded

注意

在 Core.EventReceiver 项目属性中,仅 “处理已安装的应用”“处理应用卸载” 属性可用。 此代码示例展示了如何在加载项安装过程中使用 AppInstalled 事件将 ItemAdded 事件处理程序添加到主机 Web 上的列表。

注意

本文中的代码按原样提供,不提供任何明示或暗示的担保,包括对特定用途适用性、适销性或不侵权的默示担保。

public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties)
        {

            SPRemoteEventResult result = new SPRemoteEventResult();

            switch (properties.EventType)
            {
                case SPRemoteEventType.AppInstalled:
                    HandleAppInstalled(properties);
                    break;
                case SPRemoteEventType.AppUninstalling:
                    HandleAppUninstalling(properties);
                    break;
                case SPRemoteEventType.ItemAdded:
                    HandleItemAdded(properties);
                    break;
            }


            return result;
        }

HandleAppInstalled 调用 RemoteEventReceiverManager.cs 中的 RemoteEventReceiverManager.AssociateRemoteEventsToHostWeb

 private void HandleAppInstalled(SPRemoteEventProperties properties)
        {
            using (ClientContext clientContext =
                TokenHelper.CreateAppEventClientContext(properties, false))
            {
                if (clientContext != null)
                {
                    new RemoteEventReceiverManager().AssociateRemoteEventsToHostWeb(clientContext);
                }
            }
        }

AssociateRemoteEventsToHostWeb 创建或启用 Core.EventReceivers 外接程序所使用的各种 SharePoint 对象。 您的要求可能会有所不同。 AssociateRemoteEventsToHostWeb 将执行以下操作:

  • 使用 Web.Features.Add 启用推送通知功能。

  • 使用 clientContext 对象搜索某个列表。 如果此列表不存在,CreateJobsList 会创建此列表。 如果此列表存在,会使用 List.EventReceivers 来搜索名为 ItemAddedEvent 的现有事件接收器。

  • 如果 ItemAddedEvent 事件接收器不存在:

    • 实例化一个新的 EventReceiverDefinitionCreationInformation 对象来创建新远程事件接收器。 ItemAdded 事件接收器类型将添加到 EventReceiverDefinitionCreationInformation.EventType

    • EventReceiverDefinitionCreationInformation.ReceiverURL 设置为 AppInstalled 远程事件接收器的 URL。

    • 使用 List.EventReceivers.Add 将新的事件接收器添加到此列表。

public void AssociateRemoteEventsToHostWeb(ClientContext clientContext)
        {
            // Add Push Notification feature to host web.
            // Not required but it is included here to show you
            // how to activate features.
            clientContext.Web.Features.Add(
                     new Guid("41e1d4bf-b1a2-47f7-ab80-d5d6cbba3092"),
                     true, FeatureDefinitionScope.None);


            // Get the Title and EventReceivers lists.
            clientContext.Load(clientContext.Web.Lists,
                lists => lists.Include(
                    list => list.Title,
                    list => list.EventReceivers).Where
                        (list => list.Title == LIST_TITLE));

            clientContext.ExecuteQuery();

            List jobsList = clientContext.Web.Lists.FirstOrDefault();

            bool rerExists = false;
            if (null == jobsList)
            {
                // List does not exist, create it.
                jobsList = CreateJobsList(clientContext);

            }
            else
            {
                foreach (var rer in jobsList.EventReceivers)
                {
                    if (rer.ReceiverName == RECEIVER_NAME)
                    {
                        rerExists = true;
                        System.Diagnostics.Trace.WriteLine("Found existing ItemAdded receiver at "
                            + rer.ReceiverUrl);
                    }
                }
            }

            if (!rerExists)
            {
                EventReceiverDefinitionCreationInformation receiver =
                    new EventReceiverDefinitionCreationInformation();
                receiver.EventType = EventReceiverType.ItemAdded;

                // Get WCF URL where this message was handled.
                OperationContext op = OperationContext.Current;
                Message msg = op.RequestContext.RequestMessage;
                receiver.ReceiverUrl = msg.Headers.To.ToString();

                receiver.ReceiverName = RECEIVER_NAME;
                receiver.Synchronization = EventReceiverSynchronization.Synchronous;

                // Add the new event receiver to a list in the host web.
                jobsList.EventReceivers.Add(receiver);
                clientContext.ExecuteQuery();

                System.Diagnostics.Trace.WriteLine("Added ItemAdded receiver at " + receiver.ReceiverUrl);
            }
        }

将某个项目添加到“远程事件接收器作业”列表时,AppEventReceiver.svc.cs 中的 ProcessEvent 处理 ItemAdded 事件,然后调用 HandleItemAddedHandleItemAdded 调用 RemoteEventReceiverManager.ItemAddedToListEventHandlerItemAddedToListEventHandler fetches the list item that was added, and adds the string Updated by ReR to the list item's description.

 public void ItemAddedToListEventHandler(ClientContext clientContext, Guid listId, int listItemId)
        {
            try
            {
                List photos = clientContext.Web.Lists.GetById(listId);
                ListItem item = photos.GetItemById(listItemId);
                clientContext.Load(item);
                clientContext.ExecuteQuery();

                item["Description"] += "\nUpdated by RER " +
                    System.DateTime.Now.ToLongTimeString();
                item.Update();
                clientContext.ExecuteQuery();
            }
            catch (Exception oops)
            {
                System.Diagnostics.Trace.WriteLine(oops.Message);
            }

        }

另请参阅