在 SharePoint 加载项中处理事件
自定义代码可以处理提供程序托管的外接程序中的三类事件:
- 列表事件,如在网站上添加或删除列表。
- 列表项事件,如编辑列表中的项目。
- 加载项事件,如安装加载项。
SharePoint 托管的 SharePoint 加载项不支持事件处理,但是可通过设置一个事件以触发工作流,将工作流转换为一种列表或列表项事件处理程序。 有关详细信息,请参阅 SharePoint 中的工作流。 无法通过加载项事件触发工作流,因此无法使用 SharePoint 托管的加载项处理加载项事件。
注意
网站事件和网站集事件在 SharePoint 加载项中不受支持。
有两种类型的事件:
前期事件在 SharePoint 基础结构自行处理任意事件(包括提交对内容数据库的更改)之前触发。 在 SharePoint 中,自定义前期事件处理程序始终同步执行。 在其他目的中,它们可用于取消事件。 例如,如果加载项具有删除列表的功能,那么在不满足某些条件的情况下,删除事件列表的处理程序可以取消删除。 如果事件是事件序列的一部分,取消它可以杜绝任何后续事件的发生。 例如,如果 ItemAdding 事件的处理程序取消事件,则不会触发通常会在后面发生的 ItemAdded 事件。
后期事件在 SharePoint 基础结构自行处理任意事件后触发。 在 SharePoint 中,列表和列表项事件的远程后期事件处理程序始终以异步方式执行。 (应用程序事件是一个例外。)在其他目的中,它们可用于记录事件。
处理列表和列表项事件
若要处理列表和列表项事件,您需创建远程事件接收器 (RER),也就是运行在 SharePoint 场或 SharePoint Online 之外的 Web 服务。 RER 服务的 URL 是为其处理的事件进行注册的。 有两种注册处理程序的方法:
主机 Web 中的事件以编程方式在 CSOM(客户端对象模型)或 SharePoint REST API 中注册。 此任务通常在加载项或加载项事件的处理程序中以“首次运行”逻辑完成。 (有关加载项事件的概述,请参阅本文后面的处理加载项事件。)有关以编程方式注册列表事件的代码示例,请参阅 SharePoint/PnP/Samples/Core.EventReceivers。
加载项 Web 中的事件通常在具有一些简单 XML 标记的加载项 Web 功能中注册。 有关如何创建标记和服务的详细信息,可参阅在 SharePoint 加载项中创建远程事件接收器。还有可能以编程方式注册加载项 Web 事件。
注意
在服务器场解决方案中,RER 的作用和事件接收器相同,但事件接收器有运行在 SharePoint 服务器上的自定义代码,所以它们不能用在 SharePoint 加载项中。
加载项可以处理以下列表和文档库事件。 以“ing”结尾的事件为前期(同步)事件,以“ed”结尾的事件则为后期(异步)事件。
前期(同步) | 后期(异步) |
---|---|
ListAdding | ListAdded |
ListDeleting | ListDeleted |
FieldAdding | FieldAdded |
FieldDeleting | FieldDeleted |
FieldUpdating | FieldUpdated |
字段更新事件是有关更改列表上字段(列)属性的事件(例如是否可排序),而不是有关更改字段中数据的事件。
加载项可以处理以下列表项事件。
前期(同步) | 后期(异步) |
---|---|
ItemAdding | ItemAdded |
ItemUpdating | ItemUpdated |
ItemDeleting | ItemDeleted |
ItemCheckingOut | ItemCheckedOut |
ItemCheckingIn | ItemCheckedIn |
ItemUncheckingOut | ItemUncheckedOut |
ItemAttachmentAdding | ItemAttachmentAdded |
ItemAttachmentDeleting | ItemAttachmentDeleted |
ItemFileMoving | ItemFileMoved |
ItemVersionDeleting* | ItemVersionDeleted* |
ItemFileConverted |
注意
*这两个新事件在 Visual Studio UI 中可能不可用。 如果无法使用,则选取 ItemDeleting 或 ItemDeleted,然后手动更改名称。
当您在 Visual Studio 中工作,并将某个 RER 添加到 SharePoint 外接程序项目中时,Visual Studio Office 开发人员工具 将执行以下操作:
诸如"RemoteEventReceiver1.svc"之类的 Web 服务文件会添加到 Web 应用程序中,以处理向 SharePoint 外接程序添加远程事件接收器时指定的事件。 此 Web 服务包含用于处理远程事件的代码文件。
创建远程事件接收器之后,可向 Web 应用程序服务的代码文件添加代码以处理事件。 默认情况下,您添加了处理代码的代码文件包含以下两个方法:
ProcessEvent()
处理"之前"的事件(如本文前面表格中左侧列中的事件),并且向 SharePoint 返回一个报告应取消事件或让它继续的对象。ProcessOneWayEvent()
处理"after"事件。 它以异步方式运行,并且不会将任何内容返回到 SharePoint。
在发生已注册事件时,SharePoint 会在服务中调用相应方法,并传递一个可提供代码部分上下文信息的对象。 例如,确定事件类型(来自本文前面两个表的其中一个)后,代码就可以分支到适用于事件的逻辑。
远程事件接收器的项目项会添加到 SharePoint 外接程序项目中。 远程事件接收器的 Elements.xml 文件引用您指定的 Web 应用程序和远程事件中的 Web 服务。 以下示例显示了一个处理列表项的添加或删除的 Elements.xml 文件。
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Receivers ListTemplateId="104"> <Receiver> <Name>RemoteEventReceiver1ItemAdding</Name> <Type>ItemAdding</Type> <SequenceNumber>10000</SequenceNumber> <Url>~remoteAppUrl/RemoteEventReceiver1.svc</Url> </Receiver> <Receiver> <Name>RemoteEventReceiver1ItemDeleting</Name> <Type>ItemDeleting</Type> <SequenceNumber>10000</SequenceNumber> <Url>~remoteAppUrl/RemoteEventReceiver1.svc</Url> </Receiver> </Receivers> </Elements>
若要更改远程事件接收器处理的事件,请打开“解决方案资源管理器”,打开远程事件接收器的“属性”窗口,展开“SharePoint 事件”节点,然后仅将想要处理的事件设置为“True”。
注意
有关 RER 的其他信息,包括一些故障排除信息,请参阅远程事件接收器常见问题。
处理加载项事件
加载项事件也由远程 Web 服务处理,但它们在列表和列表项 RER 的加载项包中以不同方式进行配置,因此被当作一个单独的组件类别来处理。 对于加载项事件,远程 Web 服务在加载项清单中注册,而不是在加载项 Web 功能中注册。 加载项甚至不需要具有加载项 Web。 共有三个加载项事件,如以下各节所述。
AppInstalled 事件
在 SharePoint 完成安装加载项时需要执行的所有操作后,AppInstalled 事件会立即运行,然后会通知用户安装已完成。 尽管这是一个 after 事件,SharePoint 会同步运行您的处理程序。 在处理程序完成之后才能使用加载项,并且处理程序可以取消安装(这将导致 SharePoint 回滚作为安装过程的一部分执行的全部操作)。 实际上,这是在处理程序中捕获任何错误并指示 SharePoint 回滚安装的最佳做法。 有关详细信息,请参阅将回滚逻辑和“已完成”逻辑包括在加载项事件处理程序中。
注意
在租户范围内安装加载项时,它会被安装到加载项目录网站集,而且 AppInstalled 事件只有在那时才会运行。 加载项在租赁的多个网站中可见,但事件不会对每个网站单独运行。
除了取消加载项安装之外,该事件还可用于许多其他用途,包括:
将 SharePoint 组件安装到不能通过声明方式安装带有主机 Web 功能的主机 Web,如列表或子网站。
以编程方式使用主机 Web 或加载项 Web 注册列表和列表项事件处理程序。
设置应用实例相关的初始化设置。 例如,加载项可以有一个加载项 Web 属性包,用来保留因加载项实例而异的设置。 例如,AppInstalled 处理程序可以根据主机 Web 的网站类型(如团队网站或博客网站),将不同的值写入属性包。
注意
检查主机 Web 是否是 AppCatalog 站点,是检测该加载项是否在租户作用域内安装的好方法。 请参阅 SharePoint 加载项的租赁和部署范围。
在加载项的远程 Web 应用程序中执行应用实例相关的配置,例如将表添加到数据库中。
重要
AppInstalled 事件的实现过程必须在 30 秒内完成,否则 SharePoint 安装基础结构会认为它已失败。 此基础结构会重新运行事件,并从一开始就重复代码,至多三次。 在超过四次后,SharePoint 会回滚整个加载项安装。 有关这些事实的完整含义,请参阅将回滚逻辑和“已完成”逻辑包括在加载项事件处理程序中。
AppUninstalling 事件
从主机 Web 中删除加载项时,AppUninstalling 事件 不会 运行。 删除加载项仅将加载项移动到用户回收站。 在触发 AppUninstalling 事件之前,还需执行两个步骤。 首先,用户必须从回收站删除加载项,这会将其移至第二阶段回收站。 其次, 用户必须从第二阶段回收站中删除加载项。 最后一个任务触发 AppUninstalling 事件。 AppUninstalling 事件同步运行,用户可以使用它来取消卸载,这将使加载项停留在第二阶段回收站。
此事件处理程序的主要目的是删除或回收通过 AppInstalled(或 AppUpdated)处理程序部署的内容。 SharePoint 无法删除这些内容或将其移至回收站,因为它不知道有关这些内容的信息,至少不知道它们是加载项的组件。 一般来说,删除这些内容是一个不错的做法。 但是,在删除加载项后,无需删除那些仍然有用的内容:如果 AppInstalled 处理程序创建的列表或网站仍将继续使用,请勿在 AppUninstalling 处理程序中将其删除。
AppUpgraded 事件
在 SharePoint 完成更新加载项至新版本时需要执行的所有操作后,AppUpgraded 事件会立即运行,然后通知用户更新已完成。 和 AppInstalled 事件一样,它是后期事件,但本质上是以同步方式运行,并且是捕获错误和通知 SharePoint 回滚更新的最佳做法。
此事件处理程序可执行操作的一些示例:
添加、更改或从主机 Web 中删除加载项组件。
在加载项 Web 中,执行通过加载项 Web 功能的声明性更新语义无法完成的操作。 例如,无法删除任何带有声明性更新标记的内容,但是可以在一个 AppUpgraded 处理程序中以编程方式完成此操作。
对加载项的 Web 应用程序或远程数据库中的应用实例相关组件进行更改。
有关创建加载项事件处理程序的详细说明,可参阅在 SharePoint 加载项中创建加载项事件接收器。
将回滚逻辑和“已完成”逻辑包括在加载项事件处理程序中
如果 SharePoint 在处理这三个加载项事件中的任何一个时遇到了错误,它将取消事件,并回滚对事件中所做的任何相关更改。 加载项事件处理程序必须与此系统集成,因为如果正在实现的事件部分失败,你会希望整个事件回滚,而不是继续,从而导致处于可能已损坏的状态。 下面是处理程序通常要执行的操作:
告知 SharePoint 发生了一个错误。 加载项事件处理 Web 服务返回到 SharePoint 的 SOAP 消息包含一个 Status 属性,该属性的值可以是 Continue、CancelWithError 或 CancelWithoutError。 任一取消状态均指示 SharePoint 回滚事件。
回滚处理程序在处理程序遇到错误之前已经完成的操作。 SharePoint 通常不会为你执行此操作,因为它不知道你的处理程序执行了哪些操作。 这不是通用规则。 例如,如果取消加载项安装,SharePoint 会删除整个加载项 Web,因此,AppInstalled 事件处理程序还原它对加载项 Web 所执行的一切操作不具备任何意义。 但是,通常情况下应该会回滚它对主机 Web 或加载项的远程组件所执行的操作。
注意
前面的要点适用于 AppUninstalling 事件,也同样适用于其他两个加载项事件。 例如,如果卸载事件的处理程序删除远程数据库中的某一行,然后遇到错误,那么就需要恢复该行。 由于服务向 SharePoint 发送了一条取消消息,所以不会从回收站删除加载项。 如果从中恢复并再次使用,它可能无法在没有数据库项的情况下工作。 然而,AppUninstalling 处理程序在 SharePoint 从回收站删除加载项之前完成了任务。 因此,如果 SharePoint 本身遇到错误并需要取消删除,处理程序就无法撤销它所完成的操作。
如果 SharePoint 在 30 秒内没有收到来自处理程序的结果消息,它会再次调用处理程序。 它会在尝试三次之后(总共可以尝试四次)完全放弃,并回滚事件。 每次调用处理程序时,代码从一开始就会重新开始运行。 但是通常不希望处理程序重做已经执行过的操作,比如在主机 Web 上创建一个列表,并且在处理程序超时之前,无法得知回滚逻辑是否已完成,甚至是否已触发。出于这个原因,如果不首先检查操作是否已完成,则处理程序逻辑不应采取任何操作,除非再次执行不会产生不良影响。
可以在 SharePoint UI 中看到安装和更新错误,如下图所示。
获取安装错误的详细信息
加载项事件处理程序的体系结构策略
以伪代码表示,处理程序的结构通常应如下所示。 如果 Try 部分中出现错误,则应调用 Catch 和 Rollback 部分。 (根据语言和 framework.)
Try
If X not already done,
Do X.
Catch
Send cancel message to SharePoint.
If X not already undone,
Undo X.
但是,在 Web 服务中实现回滚和“已完成”逻辑会使处理程序的速度变慢。 安装和回滚逻辑通常会对来自 Web 服务的远程内容(如 SharePoint 主机 Web 或后端数据库)或多或少进行更改。 如果安装和回滚代码在 Try 和 Catch 部分之间分割,服务将分别调用远程组件,通常在每个部分中都有几个这样的调用。
最佳做法通常是在远程组件本身实现安装和回滚逻辑,这个过程可以从 Try 部分的处理程序调用。 该过程应返回成功或失败消息,如果它报告失败,Try 部分中的代码将调用 Catch 部分(例如,引发一个异常)。 Catch 部分所执行的唯一操作就是通知 SharePoint。 我们将此称为“处理程序委派策略”。 下面的伪代码演示了该策略:
Try
Call the "Do X" procedure on remote platform.
If remote platform reports failure, call Catch.
Catch
Send cancel message to SharePoint.
在远程系统上执行的“执行 X”过程本身将包含回滚和“已完成”逻辑,如下所示。
Try
If X not already done,
Do X.
Set success flag to true.
Catch
If X was done before error,
Undo X.
Set success flag to false.
Send
Return success flag to the event handler.
例如,如果处理程序需要对 SQL Server 数据库执行操作,可以在使用 TRY-CATCH 块的 SQL Server 上安装一个存储程序,以实现安装回滚逻辑。使用 IF-ELSE 块来实现“已完成”逻辑。
SharePoint 加载项模型未提供在 SharePoint 中存储自定义服务器端代码并从 CSOM(客户端对象模型)调用此代码的方法。 但是 CSOM 提供了一种方法来捆绑 try-catch 和 if-else 逻辑,并将其发送给服务器进行执行。
有关使用处理程序委派策略向主机 Web 添加列表的加载项事件处理程序的详细示例,请参阅在 SharePoint 加载项中创建加载项事件接收器。有关代码示例,请参阅 SharePoint/PnP/Samples/Core.AppEvents.HandlerDelegation。
处理程序委派策略不能一直使用。 例如,如果处理程序调用多个组件,如数据库和 SharePoint 主机 Web,一个可能会成功完成,而另一个可能会失败。 在此场景中,如果使用处理程序委派策略来设计第一个组件的回滚逻辑,它将不会运行。 因此,如果同步调用组件,那么只有最后一个调用的组件能够使用处理程序委派策略。 如果以异步方式调用组件,就无法在其中任何一个组件中使用该策略。
有关不使用处理程序委派策略的外接程序事件处理程序示例,请参阅 SharePoint/PnP/Samples/Core.AppEvents。
提示
如果 AppInstalled 事件失败,SharePoint 会删除加载项 Web(如果有);如果 AppUpated 事件失败,SharePoint 会将加载项 Web 恢复到它的预更新状态。 因此,处理程序永远不需要回滚它们对加载项 Web 所执行的操作。 如果处理程序同时在主机 Web 和加载项 Web 上执行操作,它应首先处理加载项 Web。 这样做可以将处理程序委派策略安全地用于主机 Web。 即使加载项 Web 操作成功而主机 Web 操作失败,也不会有回滚逻辑显示未执行。
支持多个安全区域的加载项中的远程事件接收器
设计支持多个安全区域且具有远程事件接收器的加载项时存在一些限制。
远程事件接收器常见问题
以下是在使用远程事件接收器时可能会遇到的常见问题。
远程事件接收器与 SharePoint 2010 中的事件接收器有何不同?
在 SharePoint 2010 中,事件接收者通过在 SharePoint 服务器上(完全信任或者在沙箱中)运行代码来处理在 SharePoint 列表、网站以及其他 SharePoint 对象上发生的事件。 在 SharePoint 中仍然存在这种类型的事件接收器。 但是,SharePoint 还支持远程事件接收器,触发事件时运行的代码由 Web 服务托管。 这意味着,如果注册远程事件接收器,还需要告诉 SharePoint 要调用哪个 Web 服务。
在以下代码示例中,第一个示例(SharePoint 解决方案)使用事件处理程序来实现功能。 第二个示例(SharePoint 加载项)通过使用远程事件接收器来实现相同的功能。
SharePoint 解决方案
// Trigger an event when an item is added to the SharePoint list.
Public class OnPlantUpdated : SPItemEventReceiver
{
Public override void ItemAdding (SPItemEventProperties properties)
{
Properties.After.Properties.ChangedProperties.Add("Image",CreateLink(properties));
Properties.status =SPEventReceiverStatus.Continue;
}
/// When an item updates, run the following.
Public override void ItemUpdating(SPItemEventProperties properties)
{
Properties.AfterProperties.ChangedProperties.Add("Image",CreateLink9properties));
Properties.Status= SPEventReceiverStatus.Continue;
}
SharePoint 加载项
/* Trigger an event when an item is added to the SharePoint list*/
Public class OnPlantUpdated : IRemoteEventService
{
public SPRemoteEventResult ProcessEvent (SPRemoteEventProperties properties)
{
SPRemoteEventResult result =new SPRemoteEventResult();
If (properties.EventType == SPRemoteEventType.ItemAdding ||
properties.EventType == SPRemoteEventType.ItemUpdating)
{
// Add code that runs when an item is added or updated.
}
有关完整的代码示例,请参阅使用远程事件接收器添加列表项属性。
有关代码示例的详细演示,请参阅将 SharePoint 事件接收器迁移到远程事件接收器。
有关详细信息,请参阅 SPRemoteEventType 枚举
远程事件接收器如何工作?
下图显示了远程事件接收器的工作方式:
用户在 SharePoint 上执行操作(例如,编辑列表项)。
然后 SharePoint 会与已注册的 Web 服务联系。 可以执行一些操作(例如,更新列表项属性或更新后端系统)。
Web 服务还可以与访问控制服务 (ACS) 联系,来请求自己的签名令牌以回调到 SharePoint。 由于之前对列表项或在后端系统中执行的操作,您可以通过令牌从 Web 服务内部执行远程操作。
表情事件接收器在 SharePoint 中的工作原理
如何调试远程事件接收器?
请参阅在 SharePoint 加载项中调试远程事件接收器并排查故障。
我能否从远程事件接收器运行客户端 (JavaScript) 代码?
否,无法从远程事件接收器运行客户端 (JavaScript) 代码。
关于远程事件接收器可以托管在其 URL 上的位置是否有任何限制?
远程事件接收器可以托管在云中或还未用作 SharePoint 服务器的本地服务器上。 生产接收器的 URL 不能指定特定端口。 这意味着必须为 HTTPS 使用我们建议的端口 443,或为 HTTP 使用端口 80。 如果使用的是 HTTPS 且接收器服务托管在本地,但加载项位于 SharePoint Online 上,则托管服务器必须具有来自证书颁发机构的公开受信任的证书。 (只有在加载项位于本地 SharePoint 场时,自签名证书才可用。)
升级后 SharePoint 2010 事件处理程序能否在 SharePoint 上运行?
如果包含事件处理程序的 SharePoint 2010 解决方案包已升级到 SharePoint,根据自定义设置,解决方案包可以在不进行任何修改的情况下正常运行。 这同样包括事件处理程序。 如果 SharePoint 2010 解决方案被改造成 SharePoint 中的一个 SharePoint 加载项,则事件处理程序应重写为远程事件接收器。 请参阅将 SharePoint 事件接收器迁移到远程事件接收器。