Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit pass on protocol methods doc #42396

Merged
merged 10 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 23 additions & 26 deletions docs/azure/sdk/protocol-convenience-methods.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
title: Understand Azure SDK client library method types
description: Learn about the key differences between Azure SDK client library protocol and convenience methods.
description: Learn about the key differences between protocol and convenience methods in the Azure SDK client libraries for .NET.
ms.topic: conceptual
ms.custom: devx-track-dotnet, engagement-fy23, devx-track-arm-template
ms.date: 08/29/2024
ms.date: 08/30/2024
---

# Azure SDK for .NET protocol and convenience methods overview
Expand All @@ -15,15 +15,13 @@ The Azure SDK client libraries provide an interface to Azure services by transla
An Azure SDK for .NET client library can expose two different categories of methods to make requests to an Azure service:

- **Protocol methods** provide a thin wrapper around the underlying REST API for a corresponding Azure service. These methods map primitive input parameters to HTTP request values and return a raw HTTP response object.

- **Convenience methods** provide a convenience layer over the lower-level protocol layer to add support for the .NET type system and other benefits. Convenience methods accept primitives or .NET model types as parameters and map them to the body of an underlying REST API request. These methods also handle various details of request and response management to allow developers to focus on sending and receiving data objects, instead of lower-level concerns.

### Azure SDK client library dependency patterns

Protocol and convenience methods implement slightly different patterns based on the underlying package dependency chain of the respective library. An Azure SDK for .NET client library depends on one of two different foundational libraries:

- [**Azure.Core**](/dotnet/api/overview/azure/core-readme) provides shared primitives, abstractions, and helpers for building modern Azure SDK client libraries. These libraries follow the [Azure SDK Design Guidelines for .NET](https://azure.github.io/azure-sdk/dotnet_introduction.html) and use package names and namespaces prefixed with *Azure*, such as [`Azure.Storage.Blobs`](/dotnet/api/overview/azure/storage.blobs-readme).

- [**System.ClientModel**](/dotnet/api/overview/azure/system.clientmodel-readme) is a core library that provides shared primitives, abstractions, and helpers for .NET service client libraries. The `System.ClientModel` library is a general purpose toolset designed to help build libraries for various platforms and services, whereas the `Azure.Core` library is specifically designed for building Azure client libraries.

> [!NOTE]
Expand All @@ -34,8 +32,8 @@ The following table compares some of the request and response types used by prot
| Request or response concern | Azure.Core | System.ClientModel |
|-------------------------------|----------------------------------|-------------------------------------------------------|
| Request body | <xref:Azure.Core.RequestContent> | <xref:System.ClientModel.BinaryContent> |
| Advanced options | <xref:Azure.RequestContext> | <xref:System.ClientModel.Primitives.RequestOptions> |
| Raw HTTP Response | <xref:Azure.Response> | <xref:System.ClientModel.Primitives.PipelineResponse> |
| Advanced request options | <xref:Azure.RequestContext> | <xref:System.ClientModel.Primitives.RequestOptions> |
| Raw HTTP response | <xref:Azure.Response> | <xref:System.ClientModel.Primitives.PipelineResponse> |
| Return type with output model | <xref:Azure.Response%601> | <xref:System.ClientModel.ClientResult%601> |

The sections ahead provide implementation examples of these concepts.
Expand All @@ -52,7 +50,7 @@ Azure SDK client libraries adhering to the [latest design guidelines](https://az

The following code uses a `ContentSafetyClient` to call the `AnalyzeText` convenience method:

:::code source="snippets/protocol-convenience-methods/AzureCoreConvenience/Program.cs" highlight="10":::
:::code source="snippets/protocol-convenience-methods/AzureCore/Convenience/Program.cs" highlight="10":::

The preceding code demonstrates the following `Azure.Core` convenience method patterns:

Expand All @@ -63,17 +61,18 @@ The preceding code demonstrates the following `Azure.Core` convenience method pa

The following code uses a `ContentSafetyClient` to call the `AnalyzeText` protocol method:

:::code source="snippets/protocol-convenience-methods/AzureCoreProtocol/Program.cs" highlight="19-24":::
:::code source="snippets/protocol-convenience-methods/AzureCore/Protocol/Program.cs" highlight="19-24":::

The preceding code demonstrates the following protocol method patterns:
The preceding code demonstrates the following `Azure.Core` protocol method patterns:

- Uses the `RequestContent` type to supply data for the request body.
- Uses the `RequestContext` type to configure request options.
- Returns data using the `Response` type.
- Reads content from the response data into a [dynamic](../../csharp/advanced-topics/interop/using-type-dynamic.md) type using <xref:Azure.AzureCoreExtensions.ToDynamicFromJson%2A>. For more information, see [Announcing dynamic JSON in the Azure Core library for .NET](https://devblogs.microsoft.com/azure-sdk/dynamic-json-in-azure-core/).
1. Create the request, using a `RequestContent` object for the request body.
1. Invoke the protocol method, using a `RequestContext` object to configure request options.
1. Handle the response by reading:
- The HTTP status code from the `Response` object to determine whether success or failure.
- Data from the `Response` object's content into a [dynamic](../../csharp/advanced-topics/interop/using-type-dynamic.md) type using <xref:Azure.AzureCoreExtensions.ToDynamicFromJson%2A>. For more information, see [Announcing dynamic JSON in the Azure Core library for .NET](https://devblogs.microsoft.com/azure-sdk/dynamic-json-in-azure-core/).

> [!NOTE]
> The preceding code configures the `ClientErrorBehaviors.NoThrow` for the `RequestOptions`. This option prevents non-success service responses status codes from throwing an exception, which means the app code should manually handle the response status code checks.
> The preceding code configures the [ErrorOptions.NoThrow](/dotnet/api/azure.erroroptions) behavior. This option prevents non-success service responses status codes from throwing an exception, which means the app code should manually handle the response status code checks.

---

Expand All @@ -85,7 +84,7 @@ Some client libraries that connect to non-Azure services use patterns similar to

Consider the following code that uses a `ChatClient` to call the `CompleteChat` convenience method:

:::code source="snippets/protocol-convenience-methods/SCMConvenience/Program.cs" highlight="9":::
:::code source="snippets/protocol-convenience-methods/SCM/Convenience/Program.cs" highlight="9":::

The preceding code demonstrates the following `System.ClientModel` convenience method patterns:

Expand All @@ -96,14 +95,15 @@ The preceding code demonstrates the following `System.ClientModel` convenience m

The following code uses a `ChatClient` to call the `CompleteChat` protocol method:

:::code source="snippets/protocol-convenience-methods/SCMProtocol/Program.cs" highlight="26-31":::
:::code source="snippets/protocol-convenience-methods/SCM/Protocol/Program.cs" highlight="26-31":::

The preceding code demonstrates the following `System.ClientModel` protocol method patterns:

- Uses the `BinaryContent` type as a parameter to supply data for the request body.
- Uses the `RequestContext` type to configure request options.
- Returns data using the `ClientResult` type.
- Calls the <xref:System.ClientModel.ClientResult.GetRawResponse%2A> method to access the response data.
1. Create the request, using a `BinaryContent` object for the request body.
1. Invoke the protocol method, using a `RequestOptions` object to configure request options.
1. Handle the response by reading:
- The HTTP status code from the `PipelineResponse` object to determine whether success or failure.
- Data from the `PipelineResponse` object's content using `System.Text.Json` APIs.

> [!NOTE]
> The preceding code configures the [ClientErrorBehaviors.NoThrow](/dotnet/api/system.clientmodel.primitives.clienterrorbehaviors) behavior for the `RequestOptions`. This option prevents non-success service responses status codes from throwing an exception, which means the app code should manually handle the response status code checks.
Expand All @@ -113,9 +113,8 @@ A `System.ClientModel`-based response can be processed like a convenience model,
```diff
PipelineResponse response = result.GetRawResponse();

- BinaryData output = result.GetRawResponse().Content;
- using JsonDocument outputAsJson = JsonDocument.Parse(output);
- JsonElement message = outputAsJson.RootElement
- using JsonDocument output = JsonDocument.Parse(response.Content);
- JsonElement message = output.RootElement
- .GetProperty("choices"u8)[0]
- .GetProperty("message"u8);

Expand Down Expand Up @@ -147,6 +146,4 @@ Protocol methods:

## See also

- [Understanding the Azure Core library for .NET](https://devblogs.microsoft.com/azure-sdk/understanding-the-azure-core-library-for-net/)
- [Azure.Core library for .NET](/dotnet/api/overview/azure/core-readme)
- [System.ClientModel library for .NET](/dotnet/api/overview/azure/system.clientmodel-readme)
[Understanding the Azure Core library for .NET](https://devblogs.microsoft.com/azure-sdk/understanding-the-azure-core-library-for-net/)
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.AI.ContentSafety" Version="1.0.0" />
<PackageReference Include="Azure.Identity" Version="1.12.0" />
<PackageReference Include="Azure.AI.ContentSafety" />
<PackageReference Include="Azure.Identity" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="Azure.AI.ContentSafety" Version="1.0.0" />
<PackageVersion Include="Azure.Identity" Version="1.12.0" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.AI.ContentSafety" Version="1.0.0" />
<PackageReference Include="Azure.Identity" Version="1.12.0" />
<PackageReference Include="Azure.AI.ContentSafety" />
<PackageReference Include="Azure.Identity" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="OpenAI" Version="2.0.0-beta.10" />
<PackageReference Include="OpenAI" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="OpenAI" Version="2.0.0-beta.10" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,8 @@
throw new ClientResultException(response);
}

BinaryData output = result.GetRawResponse().Content;
using JsonDocument outputAsJson = JsonDocument.Parse(output);
JsonElement message = outputAsJson.RootElement
using JsonDocument output = JsonDocument.Parse(response.Content);
JsonElement message = output.RootElement
.GetProperty("choices"u8)[0]
.GetProperty("message"u8);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="OpenAI" Version="2.0.0-beta.10" />
<PackageReference Include="OpenAI" />
</ItemGroup>

</Project>
Loading