WebAPIService 类库 (C#)

WebAPIService 是一个示例 .NET 6.0 类库项目,演示了使用 Dataverse Web API 时应包括的几个重要功能。

此库演示:

  • 使用 .NET 复原能力和暂时性故障处理库 Polly 管理 Dataverse 服务保护限制
  • 使用 IHttpClientFactory 在 .NET 中管理 HttpClient
  • 使用配置数据管理客户端的行为。
  • 管理 Dataverse Web API 返回的错误。
  • 通过某种模式进行代码重用:

注释

此示例库是所有 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 类的实例,该实例包含两个必需属性:GetAccessTokenUrl。 所有其他属性都表示具有默认值的选项。

构造函数使用依赖注入来创建一个IHttpClientFactory,可以返回一个具备ConfigureHttpClient函数中指定属性的命名HttpClient。 此客户端是否使用 Cookie 取决于是否设置了 Config.DisableCookies 参数。 在构造函数中,由静态 GetRetryPolicy 方法定义的策略控制暂时性错误和 Dataverse 服务保护限制的管理方式。

服务方法

Service 类具有以下方法:

SendAsync 方法

此方法最终负责所有操作。

此方法:

SendAsync<T> 方法

此方法有助于返回一个类,该类包含 OData Actions 和 Dataverse Web API 中函数返回的 ComplexTypes 中的属性。

以下示例演示如何与 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.HttpResponseMessagesBatchRequest.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)

创建实体引用,使用EntitySetNameGuid

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 操作中记录的参数引用。

错误类

ODataErrorErrorODataException 类用于反序列化服务返回的错误。 无需直接与他们合作。

服务异常 (ServiceException)

ServiceException 是一个 异常类 ,包含服务返回的错误的属性。 使用 ParseError 方法 获取此异常的实例。

Extensions

WebApiService 具有 .NET 类型的一个扩展方法。

HttpResponseMessage As<T>

该扩展程序实例化一个T实例,其中T是从HttpResponseMessage派生的,并将T的属性复制到该派生类中。 Service SendAsync<T> 方法使用此方法,但也可以单独使用。 例如,使用 BatchRequest 类时,项 BatchResponse.HttpResponseMessages 属于 HttpResponseMessage 类型。 可以使用此扩展将它们转换为适当的派生类,以便访问任何属性。

Messages

Messages 文件夹包括从 HttpRequestMessageHttpResponseMessage 继承的类。

这些类提供了可重用的请求和响应定义,这些定义与可在任何 Dataverse 环境中使用的 OData 操作相对应。

这些类还提供了可以使用 HttpRequestMessageHttpResponseMessage 无需从这些类型派生的具体操作示例。

在应用程序中,还可以创建自定义消息,例如,使用相同的模式表示环境中的自定义 API。 这些是模块化类,不需要包含在 WebAPIService.Messages 文件夹中。

例如,在安装包含自定义 API 的解决方案之前, Web API 函数和作示例(C#) 使用 Dataverse 中不包含的自定义 API。 用于使用此消息的相应类的定义位于使用该消息的示例应用程序中:

*请求类

这些类通常具有一个带参数的构造函数,该构造函数使用执行操作所需的数据来实例化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 方法 发送这些请求。

*响应类提供类型化属性来访问 HttpResponseMessageHeadersContent 属性并对其进行分析,以提供对作返回的复杂类型的访问。

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外部。

ChangeSetsRequests被设置时,它们将被封装到HttpMessageContent中,并添加到请求的Content中。 专用 ToMessageContent 方法对标头应用所需的更改,并返回适用于 ChangeSetsRequests 属性的 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 文件夹包含与作为消息的参数或响应属性所需的 ComplexTypesEnumType 对应的任何类或枚举。

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#)