任务、会议、文件的虚拟表
警告
模型驱动应用程序的协作控件将于 2024 年 5 月停用。 退休将分两个阶段进行,以确保平稳过渡。 下表详细介绍了停用过程的时间线及其影响:
Timeframe | 操作 | 影响 |
---|---|---|
2024 年 2 月 | 将不再可从 AppSource 安装协作控件。 | - 无法在 Power Apps 环境中部署协作控件。 - 现有安装不受影响。 |
2024 年 5 月 | 为控件提供支持的内部服务将停用。 | - 控件将停止支持与 Microsoft 365 集成,并将错误返回给用户。 通过控件生成和管理的数据不会受到影响。 有关详细信息,请参阅本文后面的表。 |
通过控件创建和管理的项目在服务停用后将继续存在。
控制 | 影响 |
---|---|
审批 | 在“审批”控件中创建的审批将保留在“审批”应用中,但不再可在“审批”控件中访问。 |
Files | 在“文件”控件中管理的文件将保留在 SharePoint 中,但不再可在“文件”控件中访问。 |
会议 | 在“会议”控件中创建的会议将保留在 Outlook 和 Teams 日历中,但不再可在“会议”控件中访问。 |
注意 | 在 Notes 控件中创建的备注将保留在 Dataverse 备注表中。 |
Tasks | 在任务控件中创建的任务将保留在 Planner 中,但不再可在 Task 控件中访问。 |
建议从所有 Power Apps 解决方案中删除协作控件和协作连接器,并为即将停用的协作控件的用户做好准备。
此版本的新功能是一组虚拟表。 开发人员可以通过 OData API 与 Graph 交互。
协作控制核心解决方案包括一组 虚拟表,可用于以编程方式访问协作控件创建的数据。 协作控件仅在 公共开发人员预览版中可用。
协作控件使用的外部系统Microsoft Graph。 有用于组日历事件、预订约会、规划器计划或任务以及 SharePoint 驱动器、文件夹和文件的虚拟表。
本文提供了示例,演示如何使用 Dataverse REST API 访问虚拟表,以执行 CRUD (创建、读取、更新和删除) 操作。
提示
- 虚拟表 也称为虚拟实体,通过将数据无缝表示为 Microsoft Dataverse 中的表来集成驻留在外部系统中的数据,而无需复制数据,通常无需自定义编码。
- 有关 Dataverse REST API 的详细信息,请参阅 使用 Microsoft Dataverse Web API。
- 虚拟表使用标准 Dataverse Web API,因此可以轻松地使用虚拟表填充应用程序中的数据。
- 虚拟表实现支持协作控制所需的复杂工作流,这些工作流在Microsoft数据中心内执行以获得最佳性能。
- 虚拟表使用标准 Dataverse 日志记录和监视功能。
安装协作控件后,可以将虚拟表视为应用程序可依赖的另一项服务。
先决条件
若要遵循本文,需要:
- 已安装协作控件的 Dataverse 环境。
- Dataverse 环境中的用户帐户,该帐户具有分配给它的 协作控制用户 角色。
- 第三方工具,例如 Post man 或某些自定义 C# 代码,可用于对Microsoft Dataverse 实例进行身份验证,以及撰写和发送 Web API 请求以及查看响应。
提示
Microsoft提供了有关如何配置连接到 Dataverse 实例并使用 Postman 通过 Web API 执行操作的 Postman 环境的信息。 请参阅 将 Postman 与 Microsoft Dataverse Web API 配合使用。
虚拟表示例方案
本指南中所述的方案使用 Planner 计划和任务虚拟表。 所述的方案与任务协作控件使用的方案相同。 从用户的角度来看,方案显示如何创建 Planner 计划,以及多个任务并将其与特定的业务记录相关联。 该方案继续显示如何检索与业务记录关联的任务,以及如何读取、更新和删除特定的规划器任务。
以下序列图说明了客户端之间的交互,客户端可以是任务协作控件、 协作 API 以及 Planner 计划和任务虚拟表。
虚拟表基本操作
本部分介绍示例方案中每个步骤的 HTTP 请求和响应。
任务 1:检索组 ID
检索 协作设置中使用的组 ID。
注意
用于在后续任务中创建计划的用户必须是此组的成员。 否则,将收到 403 禁止访问响应。
任务 2:开始协作会话
协作会话是协作根表中的记录,可用于将多个协作(例如任务、事件、约会)与业务记录相关联。
借助协作会话,可以执行与业务记录关联的日历事件列表等操作,例如,检查应用程序。
HTTP/1.1 POST https://[Organization URI]/api/data/v9.0/m365_begincollaborationsession
{
"applicationName": "{{applicationName}}",
"collaborationRootEntityId": "{{collaborationRootEntityId}}",
"collaborationRootEntityName": "{{entityName}}"
}
applicationName
:应用程序的唯一名称collaborationRootEntityName
:业务记录实体的名称collaborationRootEntityId
:特定业务记录的主键 (ID)
collaborationRootId
跟踪后续请求中所需的 。
任务 3:创建 Planner 计划
创建 Planner 计划,并将其与上面 Group ID
创建的协作会话和 collaborationRootId
相关联。
HTTP/1.1 POST https://[Organization URI]/api/data/v9.0/m365_graphplannerplans
{
"m365_collaborationrootid": "{{collaborationRootId}}",
"m365_owner": "{{groupId}}",
"m365_title": "{{planTitle}}"
}
collaborationRootId
:标识要与此计划关联的协作会话,使用任务 2 中的值groupId
:标识拥有此计划的组,使用步骤 1 中的值planTitle
:计划的标题
m365_id
跟踪后续请求中所需的 。
任务 4:创建 Planner 任务
使用 PlanId
和 collaborationRootId
创建 Planner 任务。 可以创建多个 Planner 任务,并将其与之前创建的协作会话相关联。
HTTP/1.1 POST https://[Organization URI]/api/data/v9.0/m365_graphplannertasks
{
"m365_collaborationrootid": "{{collaborationRootId}}",
"m365_planid": "{{planId}}",
"m365_title": "{{taskTitle}}",
"m365_duedatetime": "2022-05-04T08:00:00Z",
"m365_assignments": "{\"me\":{\"orderHint\":\" !\",\"@odata.type\":\"#microsoft.graph.plannerAssignment\"}}"
}
collaborationRootId
:标识要与此计划关联的协作会话,使用任务 2 中的值planId
:标识此任务分配到的计划,使用上一步中的值taskTitle
:任务的标题
m365_graphplannertaskid
跟踪后续请求中所需的 。
注意
m365_graphplannertaskid
是 Planner 任务虚拟表中记录的主键。 要与此记录交互,对虚拟表的所有后续请求都必须使用此主键。 在本文档的后续步骤中,这称为 plannerTaskId
。
应重复此步骤以在计划中创建多个任务。
任务 5:检索关联的 Planner 任务
检索与 collaborationRootId
之前创建的协作会话关联的关联的 Planner 任务。
HTTP/1.1 GET https://[Organization URI]/api/data/v9.0/ m365_graphplannertasks?$filter=m365_collaborationrootid eq '{{collaborationRootId}}'&$select=m365_graphplannertaskid,m365_title,m365_createddatetime
$filter
:使用$filter系统查询通过指定协作根记录) 的 ID 来请求与协作会话 (关联的记录。$select
:使用$select系统查询选项请求特定属性。
跟踪 , m365_id‘s
因为后续请求中需要 ID。
任务 6:检索 Planner 任务
使用 PlannerTaskID
检索 Planner 任务,以对之前创建的某个规划器任务执行读取操作。
HTTP/1.1 GET https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
plannerTaskId
:规划器任务记录的主键是m365_graphplannertaskid
属性。
跟踪 @odata.etag
属性和 属性,m365_graphplannertaskid
因为执行更新或删除操作需要这些属性。
任务 7:更新 Planner 任务
使用 PlannerTask ID
更新 Planner 任务,以对在上一步中创建的规划器任务之一执行更新操作。 若要更新规划器任务,请执行以下请求:
HTTP/1.1 PATCH https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
- 标头:If-Match: {{@odata.etag}}
{
"m365_title": "{{$planTitle}}"
}
@odata.etag
:Etag 对于任务,必须执行读取才能检索最新版本。planTitle
:更新了任务的标题
任务 8:删除 Planner 任务
使用 PlannerTask ID
删除 Planner 任务,以对上一步中创建的某个规划器任务执行删除操作。 若要删除规划器任务,请执行以下请求:
HTTP/1.1 DELETE https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
@odata.etag
:Etag 对于任务,必须执行读取才能检索最新版本。
任务 9:更新 Planner 任务详细信息
使用 PlannerTask ID
更新 Planner 任务,以对在上一步中创建的规划器任务之一执行更新操作。
HTTP/1.1 PATCH https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
标头:If-Match: {{@odata.etag}}
{
"m365_title": "{{$planTitle}}",
"m365_details": "{\"@odata.etag\":\"{{details.etag}}\",\"description\":\"Updated Task Description\"}"
}
@odata.etag
:任务的 Etag,必须执行读取才能检索最新版本。planTitle
:更新了任务的标题。@details.etag
:Etag 表示任务详细信息,必须使用查询$select查询参数执行读取,以包含m365_details
列以检索最新版本。 此值包含在m365_details
响应的 列中。 此值与 不同,@odata.etag
因为在 Planner 后端中,任务及其详细信息是单独存储的。
注意
可以将标头设置为 If-Match
“*”,然后无需提供任何 etag 值,但所做的更改将始终覆盖任务及其详细信息。
虚拟表授权
下面是使用协作控件解决方案中的虚拟表发出 HTTP 请求所需的授权步骤。
Azure 应用注册
若要获取正确的持有者令牌,需要在 Azure 中注册应用。 有关应用注册的详细信息,请参阅 注册应用。
在 Azure 门户中创建应用注册以进行身份验证。
浏览到 证书 & 机密。
创建新的客户端密码。
重要
请确保复制机密值并存储以供以后使用。 离开当前页后,将无法再次访问它。
浏览到 API 权限。
从 Dynamics CRM 添加 user_impersonation 委托权限。
授予管理员对此权限的同意。
浏览到 清单。
将以下属性的值设置为 true:
- oauth2AllowIdTokenImplicitFlow
- oauth2AllowImplicitFlow
选择“保存”。
PowerApps 环境权限
设置应用注册后,必须在 PowerApps 环境中设置应用程序用户。 这允许使用之前配置的正确 Dynamics 作用域进行身份验证。
浏览到“环境>”>Your_Environment“用户>应用用户列表”。
选择“ 新建应用用户 ”,然后选择 Azure 应用注册。
选择 “编辑安全角色” ,并将 “系统管理员” 角色分配给应用用户。
- 应用 “系统管理员” 角色以允许对具有较低安全角色的任何用户进行身份验证。 例如, 协作控制用户。
- 可以通过向应用程序应用较低的角色来限制这一点。 例如, 协作控制管理员。
获取持有者令牌
完成 Azure 应用注册和 PowerApps 环境权限后,发送以下 HTTP 请求以获取持有者令牌。
POST https://login.microsoftonline.com/<AZURE_APP_TENANT_ID>/oauth2/token
- Content-Type:application/x-www-form-urlencoded
- client_id: <AZURE_APP_CLIENT_ID>
- &client_secret: <AZURE_APP_CLIENT_ID>
- &资源:https://< RESOURCEURL>/
- &用户名: <USERNAME>
- &密码: <PASSWORD>
- &grant_type:密码
重要
请确保在资源参数中包含尾随正斜杠。 否则,在调用虚拟表时,将收到与 Graph 范围相关的错误。
从响应有效负载中,复制 access_token 属性的值。 然后,可以在向虚拟表发出请求时将此持有者令牌作为授权标头的一部分传递。
虚拟表错误处理
虚拟表错误处理描述了常见的错误方案以及虚拟表的响应方式。
尝试在没有协作会话的情况下创建虚拟记录
创建虚拟记录的每个请求都需要有效的协作会话。 创建虚拟记录时,虚拟表将创建协作映射记录,其中包括虚拟记录主键、实体名称和外部 ID,即 Graph 资源 ID。 此协作映射与协作会话相关联,这就是协作控件跟踪与业务记录关联的协作的方式。
HTTP/1.1 POST https://[Organization URI]/api/data/v9.0/m365_graphplannertasks
{
"m365_planid": "{{planId}}",
"m365_title": "{{taskTitle}}",
"m365_duedatetime": "2022-05-04T08:00:00Z",
"m365_assignments": "{\"me\":{\"orderHint\":\" !\",\"@odata.type\":\"#microsoft.graph.plannerAssignment\"}}"
}
请求 collaborationRootId
中缺少 属性。
若要解决此问题,在创建虚拟记录时必须始终提供有效的 collaborationRootId
属性。
尝试在没有协作映射的情况下读取虚拟记录
虚拟表允许执行请求,从而返回虚拟记录的集合。 在本文档的前面部分中,我们请求了与特定协作会话关联的所有规划器任务。 还可以使用 $filter
系统查询(如 $filter=m365_planid eq {{planId}}
)请求与特定规划器计划关联的所有规划器任务。 如果使用此类查询,则会发生的一个问题是,会为规划器任务返回记录,这些记录不与协作会话(即使用协作控件以外的其他方式创建的规划器任务)相关联。 如果尝试读取、更新或删除此类记录,请求将失败,因为虚拟表找不到关联的协作映射。
HTTP/1.1 GET https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
属性 plannerTaskId
与规划器任务相关联,该任务是使用 Planner Web 界面创建的,因此没有协作地图记录。
若要解决此问题,必须检查响应中的错误消息,如果它设置为上面显示的消息,则表示虚拟记录未关联。 若要为此记录创建关联,必须调用 关联协作映射 - REST API。
尝试读取虚拟记录,但 Graph 资源已被删除
与上一个错误相关,需要处理图形资源已删除,但客户端仍对已删除虚拟记录的引用的情况。 如果其他用户删除了记录,则可能会发生这种情况。 如果尝试读取、更新或删除此类记录,请求会失败,因为虚拟表无法从 Graph 检索资源。
HTTP/1.1 GET https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
属性 plannerTaskId
与已删除的规划器任务相关联。
这种情况必须由任何客户端代码处理,后者会检索虚拟记录,因为另一个用户可以随时删除关联的 Graph 资源。
尝试使用无效的更新虚拟记录 @odata.etag
属性 @odata.etag
用于数据并发,以及防止在其他用户更新同一记录时过度写入该记录。 当读取记录时,返回当前 etag,并在更改记录之前保持有效。 etag 应包含在任何更新请求中,并在操作完成之前进行检查。 如果记录在当前用户读取记录后被其他用户更改,则当前用户更新请求将失败。
如果使用相同的 @odata.etag执行两个更新请求,则第二个请求将失败:
HTTP/1.1 PATCH https://[Organization URI]/api/data/v9.0/m365_graphplannertasks({{plannerTaskId}})
标头:If-Match: {{@odata.etag}}
{
"m365_title": "{{$planTitle}}"
}
查询关联的虚拟记录
在任务 5 中,介绍了如何检索关联的 Planner 任务。 所有虚拟表都支持此操作。 执行此请求时,必须包含一个 $filter
查询,该查询指定协作根 ID,如下所示:
HTTP/1.1 GET https://[Organization URI]/api/data/v9.0/ m365_graphplannertasks?$filter=m365_collaborationrootid eq '{{collaborationRootId}}'&$select=m365_graphplannertaskid,m365_title,m365_createddatetime
- 其他筛选选项不能与此
$filter
查询结合使用,如果存在,则忽略它们。 - 其他筛选必须直接对来自请求的响应执行。
查询具有所需键属性的虚拟记录
调用 Dataverse Web API 从以下虚拟表中检索多个记录时,需要一个必需的密钥属性。 Graph Booking Appointments 要求在查询中包含有效的 m365_bookingbusinessid
。 如果未提供密钥属性,则请求失败,如下所示:
HTTP/1.1 400 Bad Request
{
"error": {
"code": "0x80048d0b",
"message": "Key attribute is missing: 'm365_bookingbusinessid'.",
….
}
}
若要解决此问题,请将请求更改为以下格式:
HTTP/1.1 GET https://[Organization URI]/api/data/v9.0/ m365_graphbookingappointments?$filter=m365_bookingbusinessid eq '{{bookingBusinessId}}'
创建虚拟记录和图形访问控制
虚拟表遵循为 Microsoft Graph 指定的访问控制。 虚拟表不允许用户无法使用 Microsoft Graph API 执行的操作。 例如,如果你用于创建计划的用户是任务 3,并且不是你使用的组的成员,则会收到 403 禁止响应。
另请参阅
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈