Azure SDK for .NET protocol and convenience methods overview

The Azure SDK client libraries provide an interface to Azure services by translating method calls into messages sent via the respective service protocol. For REST API services, this means sending HTTP requests and converting the responses into runtime types. In this article, you'll learn about the different types of methods exposed by the client libraries and explore their implementation patterns.

Understand protocol and convenience methods

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 provides shared primitives, abstractions, and helpers for building modern Azure SDK client libraries. These libraries follow the Azure SDK Design Guidelines for .NET and use package names and namespaces prefixed with Azure, such as Azure.Storage.Blobs.
  • System.ClientModel 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

The Azure.Core library itself also depends on System.ClientModel for various client building blocks. In the context of this article, the key differentiator for method patterns is whether a client library depends on Azure.Core or System.ClientModel directly, rather than through a transitive dependency.

The following table compares some of the request and response types used by protocol and convenience methods, based on whether the library depends on Azure.Core or System.ClientModel.

Request or response concern Azure.Core System.ClientModel
Request body RequestContent BinaryContent
Advanced request options RequestContext RequestOptions
Raw HTTP response Response PipelineResponse
Return type with output model Response<T> ClientResult<T>

The sections ahead provide implementation examples of these concepts.

Protocol and convenience method examples

The coding patterns and types used by client library protocol and convenience methods vary slightly based on whether the library depends on Azure.Core or System.ClientModel. The differences primarily influence the .NET types used for handling request and response data.

Libraries that depend on Azure.Core

Azure SDK client libraries adhering to the latest design guidelines depend on the Azure.Core library. For example, the Azure.AI.ContentSafety library depends on the Azure.Core library and provides a ContentSafetyClient class that exposes both protocol and convenience methods.

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

using Azure.AI.ContentSafety;
using Azure.Identity;

// Create the client
ContentSafetyClient client = new(
    new Uri("https://contentsafetyai.cognitiveservices.azure.com/"),
    new DefaultAzureCredential());

// Call the convenience method
AnalyzeTextResult result = client.AnalyzeText("What is Microsoft Azure?");

// Display the results
foreach (TextCategoriesAnalysis item in result.CategoriesAnalysis)
{
    Console.WriteLine($"{item.Category}: {item.Severity}");
}

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

  • Uses a standard C# primitive or model type as a parameter.
  • Returns a friendly C# type that represents the result of the operation.

Libraries that depend on System.ClientModel

Some client libraries that connect to non-Azure services use patterns similar to the libraries that depend on Azure.Core. For example, the OpenAI library provides a client that connects to the OpenAI services. These libraries are based on a library called System.ClientModel that has patterns similar to Azure.Core.

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

using OpenAI.Chat;

// Create the client
ChatClient client = new(
    model: "gpt-4o-mini",
    credential: Environment.GetEnvironmentVariable("OPENAI_API_KEY")!);

// Call the convenience method
ChatCompletion completion = client.CompleteChat("What is Microsoft Azure?");

// Display the results
Console.WriteLine($"[{completion.Role}]: {completion}");

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

  • Uses a standard C# primitive or model type as a parameter.
  • Returns a ClientResult type that represents the result of the operation.

Handle exceptions

When a service call fails, the service client throws an exception that exposes the HTTP status code and the details of the service response, if available. A System.ClientModel-dependent library throws a ClientResultException, while an Azure.Core-dependent library throws a RequestFailedException.

using Azure.AI.ContentSafety;
using Azure.Identity;
using Azure;

// Create the client
ContentSafetyClient client = new(
    new Uri("https://contentsafetyai.cognitiveservices.azure.com/"),
    new DefaultAzureCredential());

try
{
    // Call the convenience method
    AnalyzeTextResult result = client.AnalyzeText("What is Microsoft Azure?");

    // Display the results
    foreach (TextCategoriesAnalysis item in result.CategoriesAnalysis)
    {
        Console.WriteLine($"{item.Category}: {item.Severity}");
    }
} 
catch (RequestFailedException ex)
{
    Console.WriteLine($"Error: {ex.Message}");
}

Protocol and convenience method usage guidance

Although the Azure SDK for .NET client libraries provide the option to use either protocol or convenience methods, prioritize using convenience methods in most scenarios. Convenience methods are designed to improve the development experience and provide flexibility for authoring requests and handling responses. However, both method types can be used in your app as needed. Consider the following criteria when deciding which type of method to use.

Convenience methods:

  • Enable you to work with more friendly method parameter and response types.
  • Handle various low-level concerns and optimizations for you.

Protocol methods:

  • Provide access to lower-level types, such as RequestContext and RequestOptions, which aren't available through convenience methods.
  • Enable access to features of the underlying REST APIs that convenience methods don't expose.
  • Enable you to create your own convenience methods around service endpoints that don't already have convenience methods. This approach requires understanding the service's REST API documentation to handle requests and responses correctly.

See also

Understanding the Azure Core library for .NET