WebAPIService 是一个示例 .NET 6.0 类库项目,演示了使用 Dataverse Web API 时应包括的几个重要功能。
此库演示:
- 使用 .NET 复原能力和暂时性故障处理库 Polly 管理 Dataverse 服务保护限制。
- 使用 IHttpClientFactory 在 .NET 中管理 HttpClient。
- 使用配置数据管理客户端的行为。
- 管理 Dataverse Web API 返回的错误。
- 通过某种模式进行代码重用:
- 创建从 HttpRequestMessage 和 HttpResponseMessage 继承的类。
- 使用这些类的方法。
- 一种模块化模式,用于根据需要添加新功能。
注释
此示例库是所有 Dataverse C# Web API 示例使用的帮助程序,但它不是 SDK。 它仅经测试以确认使用它的样本已成功运行。 此示例代码提供“as-is”,不保证重复使用。
此库不支持:
- 管理身份验证。 这取决于从提供要使用的访问令牌的应用程序传递的函数。 所有 Web API 示例都依赖于使用Microsoft身份验证库(MSAL)管理身份验证的共享应用类。 MSAL 支持多种不同类型的身份验证流。 为了简单起见,这些示例使用 用户名/密码(ROPC)流, 但不建议使用此流。 对于您的应用程序,您应使用其他流之一。 详细信息: Microsoft身份验证库中的身份验证流支持。
- 提供任何代码生成功能。 示例中使用的所有类都是手动编写的。 所有业务实体数据都使用已知的 Json.NET JObject 类 ,而不是表示实体类型的类。
- 提供用于撰写 OData 查询的对象模型。 所有查询都以查询参数的形式显示 OData 查询语法。
Code
可以在 WebApiServicePowerApps-Samples/dataverse/webapi/C#-NETx/WebAPIService 中找到类库源代码和 Visual Studio 解决方案
类列表
以下类包括 WebAPIService:
服务类
该Service类提供通过使用 IHttpClientFactory 管理的 HttpClient 将请求发送到 Dataverse 的方法。
Service是所有示例的核心组件,你可以用它来完成示例代码中的任何操作。 使用示例中的WebAPIService 或任何相关内容提供了代码重用的便利,并且能够在更高水平上演示 Dataverse Web API 的功能。
Service 构造函数接受一个 Config 类的实例,该实例包含两个必需属性:GetAccessToken 和 Url。 所有其他属性都表示具有默认值的选项。
构造函数使用依赖注入来创建一个IHttpClientFactory,可以返回一个具备ConfigureHttpClient函数中指定属性的命名HttpClient。 此客户端是否使用 Cookie 取决于是否设置了 Config.DisableCookies 参数。 在构造函数中,由静态 GetRetryPolicy 方法定义的策略控制暂时性错误和 Dataverse 服务保护限制的管理方式。
服务方法
该 Service 类具有以下方法:
SendAsync 方法
此方法最终负责所有操作。
此方法:
- 具有 HttpRequestMessage 参数。
- 返回
Task<HttpResponseMessage> - 公开与 HttpClient.SendAsync(HttpRequestMessage) 方法 相同的签名,并可以采用相同的方式使用。
- 调用方法中
Config.GetAccessToken设置的函数以设置Authorization请求的标头值。 - 使用 IHttpClientFactory.CreateClient 方法 获取命名的
HttpClient以发送请求。 - 如果 HttpResponseMessage.IsSuccessStatusCode 属性为 false,则引发 ServiceException,因此在使用此方法时无需检查
IsSuccessStatusCode。
SendAsync<T> 方法
此方法有助于返回一个类,该类包含 OData Actions 和 Dataverse Web API 中函数返回的 ComplexTypes 中的属性。
- 具有 HttpRequestMessage 参数。 使用此方法时,期望请求参数是派生自
的 *响应类 之一,但这不是必需的。 - 返回
Task<T>,其中T是从HttpResponseMessage派生的类。 有关详细信息 ,请参阅 *响应类 。 - 调用 SendAsync 方法。
- 使用 HttpResponseMessage As<T> 扩展方法返回请求的类型。
以下示例演示如何与 WhoAmI 函数一起使用:
static async Task WhoAmI(Service service)
{
var response = await service.SendAsync<WhoAmIResponse>(new WhoAmIRequest());
Console.WriteLine($"Your user ID is {response.UserId}");
}
ParseError 方法
此方法解析HttpResponseMessage中因不成功HttpRequestMessage而导致的内容,以返回ServiceException。 当 HttpResponseMessage.IsSuccessStatusCode 属性为 false 时,SendAsync 方法使用此方法。 还可以使用它从 HttpResponseMessage 属性设置为 true 时返回 BatchResponse.HttpResponseMessages 的 BatchRequest.ContinueOnError 实例中提取错误信息。 详细信息: Batch
服务属性
服务具有单个属性: BaseAddress.
BaseAddress 属性
此属性返回在 . Config.Url中设置的基本 URL。 在实例化 BatchRequest 类时,您需要此 URL,并在需要绝对 URL 的任何情况下将其附加到相对 URL 之上。
配置类
Config 类包含用于控制应用程序行为的属性,如下表所示:
| 资产 | 类型 | Description |
|---|---|---|
GetAccessToken |
Func<Task<string>> |
客户端应用程序提供的用于返回访问令牌的函数。 |
Url |
string? |
环境的基本URL。 例如:https://org.api.crm.dynamics.com |
CallerObjectId |
Guid |
要用于模拟的SystemUser.ActiveDirectoryGuid值。 默认值为 Guid.Empty 详细信息: 使用 Web API 模拟其他用户 |
TimeoutInSeconds |
ushort |
等待超时的时间。 默认值为 120 秒。 |
MaxRetries |
byte |
发生服务保护限制时重试的最大次数。 默认值为 3。 |
Version |
string |
要使用的服务版本。 默认值为 v9.2 |
DisableCookies |
bool |
是否禁用 Cookie 以提高大容量数据加载方案中的性能。 详细信息: 服务器相关性 |
EntityReference 类
该 EntityReference 类表示对 Dataverse 表中记录的引用。 OData 使用 URL 标识资源。
EntityReference 提供了一些方法来简化 URL 的创建和访问属性。
EntityReference 构造函数
使用以下构造函数实例化EntityReference。
EntityReference(string entitySetName, Guid?ID)
创建实体引用,使用EntitySetName和Guid。
EntityReference(字符串 URI)
分析绝对或相对 URL 以创建实体引用,包括使用备用键的 URL。
EntityReference(string setName, Dictionary<string, string>? keyAttributes)
使用此构造函数可以使用备用键将实体引用实例化为对象。
注释
键值必须是字符串值。 这不会将其他类型转换为适当的字符串。
EntityReference 属性
EntityReference 具有以下公共属性:
| 资产 | 类型 | Description |
|---|---|---|
Id |
Guid? |
不使用备用键时记录的主键值。 |
KeyAttributes |
Dictionary<string, string> |
表示 URL 中使用的备用键值的字符串值。 |
SetName |
string |
EntitySetName实体类型的类型。 |
Path |
string |
记录的相对 URL。 |
EntityReference 方法
EntityReference 具有以下公共方法。 这两个都不需要任何参数。
| 方法名 | 返回类型 | Description |
|---|---|---|
AsODataId |
string |
返回一个字符串,该字符串的格式设置为用作对 OData 函数 URL 中的记录的参数引用。 |
AsJObject |
JObject |
返回一个 JObject,可以用作对 OData 操作中记录的参数引用。 |
错误类
ODataError、 Error和 ODataException 类用于反序列化服务返回的错误。 无需直接与他们合作。
服务异常 (ServiceException)
ServiceException 是一个 异常类 ,包含服务返回的错误的属性。 使用 ParseError 方法 获取此异常的实例。
Extensions
WebApiService 具有 .NET 类型的一个扩展方法。
HttpResponseMessage As<T>
该扩展程序实例化一个T实例,其中T是从HttpResponseMessage派生的,并将T的属性复制到该派生类中。
Service
SendAsync<T> 方法使用此方法,但也可以单独使用。 例如,使用 BatchRequest 类时,项 BatchResponse.HttpResponseMessages 属于 HttpResponseMessage 类型。 可以使用此扩展将它们转换为适当的派生类,以便访问任何属性。
Messages
该 Messages 文件夹包括从 HttpRequestMessage 或 HttpResponseMessage 继承的类。
这些类提供了可重用的请求和响应定义,这些定义与可在任何 Dataverse 环境中使用的 OData 操作相对应。
这些类还提供了可以使用 HttpRequestMessage 和 HttpResponseMessage 无需从这些类型派生的具体操作示例。
在应用程序中,还可以创建自定义消息,例如,使用相同的模式表示环境中的自定义 API。 这些是模块化类,不需要包含在 WebAPIService.Messages 文件夹中。
例如,在安装包含自定义 API 的解决方案之前, Web API 函数和作示例(C#) 使用 Dataverse 中不包含的自定义 API。 用于使用此消息的相应类的定义位于使用该消息的示例应用程序中:
- FunctionsAndActions/Messages/IsSystemAdminRequest.cs
- FunctionsAndActions/Messages/IsSystemAdminResponse.cs
*请求类
这些类通常具有一个带参数的构造函数,该构造函数使用执行操作所需的数据来实例化HttpRequestMessage。 它们可以根据需要具有单独的属性。
此模式的最简单示例是 WhoAmIRequest 类。
namespace PowerApps.Samples.Messages
{
/// <summary>
/// Contains the data to perform the WhoAmI function
/// </summary>
public sealed class WhoAmIRequest : HttpRequestMessage
{
/// <summary>
/// Initializes the WhoAmIRequest
/// </summary>
public WhoAmIRequest()
{
Method = HttpMethod.Get;
RequestUri = new Uri(
uriString: "WhoAmI",
uriKind: UriKind.Relative);
}
}
}
这些类的名称通常与 Dataverse SDK Microsoft.Xrm.Sdk.Messages 命名空间 中的类保持一致,但不限于那些操作。 Web API 提供了执行某些 SDK 无法完成的操作,例如 CreateRetrieveRequest 是用于创建和检索记录的消息。 Dataverse SDK 在单个请求中不提供此功能。
*响应类
当 *请求类返回值时,有一个相应的 *Response 类来访问返回的属性。 如果 *Request 返回 204 No Content,则操作返回一个HttpResponseMessage,但没有派生类。 使用 SendAsync 方法 发送这些请求。
*响应类提供类型化属性来访问 HttpResponseMessageHeaders 或 Content 属性并对其进行分析,以提供对作返回的复杂类型的访问。
类 WhoAmIResponse 是一个示例。 在此类中,可以找到提取WhoAmIResponse ComplexType的属性所需的所有代码。
using Newtonsoft.Json.Linq;
namespace PowerApps.Samples.Messages
{
// This class must be instantiated by either:
// - The Service.SendAsync<T> method
// - The HttpResponseMessage.As<T> extension in Extensions.cs
/// <summary>
/// Contains the response from the WhoAmIRequest
/// </summary>
public sealed class WhoAmIResponse : HttpResponseMessage
{
// Cache the async content
private string? _content;
//Provides JObject for property getters
private JObject _jObject
{
get
{
_content ??= Content.ReadAsStringAsync().GetAwaiter().GetResult();
return JObject.Parse(_content);
}
}
/// <summary>
/// Gets the ID of the business to which the logged on user belongs.
/// </summary>
public Guid BusinessUnitId => (Guid)_jObject.GetValue(nameof(BusinessUnitId));
/// <summary>
/// Gets ID of the user who is logged on.
/// </summary>
public Guid UserId => (Guid)_jObject.GetValue(nameof(UserId));
/// <summary>
/// Gets ID of the organization that the user belongs to.
/// </summary>
public Guid OrganizationId => (Guid)_jObject.GetValue(nameof(OrganizationId));
}
}
仅当 SendAsync<T> 方法返回,或通过 HttpResponseMessage属性中使用HttpResponseMessage As<T>扩展时,才能正确实例化这些类。
Batch
该 Batch 文件夹包含三个类,用于管理发送 OData $batch 请求。 详细信息: 使用 Web API 执行批处理作。
BatchRequest
构造函数 BatchRequest 初始化一个 HttpRequestMessage,可与 SendAsync<T> 方法 一起使用,以批量发送请求。 构造函数要求将 Service.BaseAddress 值作为参数传递。
BatchRequest 具有以下属性。
| 资产 | 类型 | Description |
|---|---|---|
ContinueOnError |
Bool |
控制是否在发生错误时继续批处理操作。 |
ChangeSets |
List<ChangeSet> |
要包含在批处理中的一个或多个更改集。 |
Requests |
List<HttpRequestMessage> |
一个或多个 HttpMessageRequest 要发送到任何 ChangeSet外部。 |
当ChangeSets或Requests被设置时,它们将被封装到HttpMessageContent中,并添加到请求的Content中。 专用 ToMessageContent 方法对标头应用所需的更改,并返回适用于 ChangeSets 和 Requests 属性的 HttpMessageContent。
ChangeSet
更改集表示一组必须在事务中完成的请求。
它包含单个属性:
| 资产 | 类型 | Description |
|---|---|---|
Requests |
List<HttpRequestMessage> |
在事务中要执行的一项或多项操作 HttpMessageRequest 。 |
BatchResponse
BatchResponse 具有单个属性:
| 资产 | 类型 | Description |
|---|---|---|
HttpResponseMessages |
List<HttpResponseMessage> |
操作 $batch 的响应。 |
BatchResponse 具有一个私有的 ParseMultipartContent 方法,该方法被 HttpResponseMessages 属性 getter 用于解析 MultipartContent 返回的单个 HttpResponseMessage。
若要访问返回的 HttpResponseMessage 实例的类型属性,可以使用 HttpResponseMessage 作为<T> 扩展方法。
Methods
对于经常执行的操作,Methods 文件夹包含 Service 类的扩展。 这些方法允许在单个行中使用相应的 *Request 类。
包括以下方法:
| 方法 | 返回类型 | Description |
|---|---|---|
Create |
Task<EntityReference> |
创建新记录。 |
CreateRetrieve |
Task<JObject> |
创建一个新记录并检索它。 |
Delete |
Task |
删除记录。 |
FetchXml |
Task<FetchXmlResponse> |
检索 FetchXml 查询的结果。 使用$batch发送请求POST,以解决当使用GET发送的长URL可能超过限制的问题。 |
GetColumnValue<T> |
Task<T> |
从表行中检索单个列值。 |
Retrieve |
Task<JObject> |
检索记录。 |
RetrieveMultiple |
Task<RetrieveMultipleResponse> |
检索多个记录。 |
SetColumnValue<T> |
Task |
设定表格行中某列的值。 |
Update |
Task |
更新记录。 |
Upsert |
Task<UpsertResponse> |
对记录执行 Upsert(插入或更新)。 |
在示例应用程序中,默认情况下,如果操作不代表 Dataverse 中默认找到的 API,该方法定义在应用程序本身中,而不是在 WebAPIService 中定义。
例如,在安装包含自定义 API 的解决方案之前, Web API 函数和作示例(C#) 使用 Dataverse 中不包含的自定义 API。 此方法的定义位于使用它的示例应用程序中: FunctionsAndActions/Methods/IsSystemAdmin.cs
类型
该 Types 文件夹包含与作为消息的参数或响应属性所需的 ComplexTypes 或 EnumType 对应的任何类或枚举。
Metadata
该 Metadata 文件夹包含 Messages 和与 Dataverse 架构定义相关的 Types 操作。 这些类通常有许多返回复杂类型的属性。 这些类型用于 Web API 表架构操作示例(C#)。
另请参阅
Web API 基本作示例 (C#)
Web API 查询数据示例 (C#)
Web API 条件作示例 (C#)
Web API 函数和动作示例 (C#)
Web API 表架构作示例 (C#)
Web API WebApiService 并行作示例 (C#)
使用 TPL 数据流组件的 Web API 并行操作示例 (C#)