### Example Azure SDK Service Client: ConfigurationClient (.NET) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates the application of the general Azure SDK service client design guidelines using the concrete example of `ConfigurationClient` for the Application Configuration service. It shows specific constructor and method signatures. ```csharp namespace Azure.Data.Configuration { public class ConfigurationClient { public ConfigurationClient(string connectionString); public ConfigurationClient(string connectionString, ConfigurationClientOptions options); protected ConfigurationClient(); // for mocking public virtual Task> GetConfigurationSettingAsync(string key, CancellationToken cancellationToken = default); public virtual Response GetConfigurationSetting(string key, CancellationToken cancellationToken = default); // other members … } // options for configuring the client public class ConfigurationClientOptions : ClientOptions { ... } } ``` -------------------------------- ### C# ConfigurationClient Example Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates a C# 'ConfigurationClient' class demonstrating how model types like 'ConfigurationSetting' are returned from service methods, using Task> for asynchronous operations. ```csharp public class ConfigurationClient { public virtual Task> GetAsync(...); public virtual Response Get (...); ... } ``` -------------------------------- ### C# ConfigurationSetting Model Example Source: https://azure.github.io/azure-sdk/dotnet_/introduction Defines a sealed C# class 'ConfigurationSetting' implementing IEquatable for representing REST service resources. Includes properties like Key, Value, and Tags, with specified access modifiers for control. ```csharp public sealed class ConfigurationSetting : IEquatable { public ConfigurationSetting(string key, string value, string label = default); public string ContentType { get; set; } public string ETag { get; internal set; } public string Key { get; set; } public string Label { get; set; } public DateTimeOffset LastModified { get; internal set; } public bool Locked { get; internal set; } public IDictionary Tags { get; } public string Value { get; set; } public bool Equals(ConfigurationSetting other); [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object obj); [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode(); [EditorBrowsable(EditorBrowsableState.Never)] public override string ToString(); } ``` -------------------------------- ### Configuration Client Service Methods (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates service methods for a ConfigurationClient, including operations for adding, setting, getting, and deleting configuration settings. Supports both synchronous and asynchronous operations. ```csharp public class ConfigurationClient { public virtual Task> AddAsync(ConfigurationSetting setting, CancellationToken cancellationToken = default); public virtual Response Add(ConfigurationSetting setting, CancellationToken cancellationToken = default); public virtual Task> SetAsync(ConfigurationSetting setting, CancellationToken cancellationToken = default); public virtual Response Set(ConfigurationSetting setting, CancellationToken cancellationToken = default); public virtual Task> GetAsync(string key, SettingFilter filter = default, CancellationToken cancellationToken = default); public virtual Response Get(string key, SettingFilter filter = default, CancellationToken cancellationToken = default); public virtual Task> DeleteAsync(string key, SettingFilter filter = default, CancellationToken cancellationToken = default); public virtual Response Delete(string key, SettingFilter filter = default, CancellationToken cancellationToken = default); } ``` -------------------------------- ### ContainerRegistryClient and ContainerRepository Subclient Example (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates how a `ContainerRegistryClient` (service client) provides a factory method to create a `ContainerRepository` (resource client) for managing operations on a specific repository. This illustrates the organization of related operations into subclients. ```csharp public class ContainerRegistryClient { // ... public virtual ContainerRepository GetRepository(string name); } public class ContainerRepository { protected ContainerRepository(); public virtual string Name { get; } public virtual Response Delete(CancellationToken cancellationToken = default); public virtual Response GetProperties(CancellationToken cancellationToken = default); public virtual Response UpdateProperties(ContainerRepositoryProperties value, CancellationToken cancellationToken = default); // ... } ``` -------------------------------- ### Example: BlobBaseClient CopyFromUri Operation Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates how `BlobBaseClient` uses `Operation` for initiating and managing a `CopyFromUri` operation, showcasing both automatic and manual polling, and resuming operations. ```APIDOC ## BlobBaseClient.CopyFromUri Example ### Description This example illustrates the usage of `BlobBaseClient.CopyFromUri` which returns an `Operation` representing a long-running copy operation. It covers automatic polling, manual polling using `UpdateStatusAsync`, and resuming a previously started operation using its ID. ### Method `CopyFromUri(WaitUntil wait, ..., CancellationToken cancellationToken)` `CopyFromUriAsync(WaitUntil wait, ..., CancellationToken cancellationToken)` ### Parameters - **wait** (WaitUntil): Specifies whether to wait for the operation to complete (`WaitUntil.Completed`) or to start it and poll manually (`WaitUntil.Started`). - **cancellationToken** (CancellationToken): A token for observing cancellation requests. ### Request Body (Not applicable for this example, parameters are part of the method signature) ### Request Example (Automatic Polling) ```csharp BlobBaseClient client = ...; Operation operation = await client.CopyFromUri(WaitUntil.Completed, ...); Console.WriteLine(operation.Value); ``` ### Request Example (Manual Polling) ```csharp BlobBaseClient client = ...; CopyFromUriOperation operation = await client.CopyFromUriAsync(WaitUntil.Started, ...); while (true) { await operation.UpdateStatusAsync(); if (operation.HasCompleted) break; await Task.Delay(1000); } if (operation.HasValue) Console.WriteLine(operation.Value); ``` ### Request Example (Saving Operation ID) ```csharp BlobBaseClient client = ...; CopyFromUriOperation operation = await client.CopyFromUriAsync(WaitUntil.Started, ...); string operationId = operation.Id; // Two days later, resume the operation var operation2 = new CopyFromUriOperation(operationId, client); long value = await operation2.WaitForCompletionAsync(); ``` ### Response #### Success Response (200 OK) - **Value** (long): The result of the long-running operation (e.g., the size of the copied blob). #### Response Example (Value) ```json 102400 ``` ### Notes - Client libraries should inherit from `Operation` to provide specific implementations and constructors for accessing existing LROs. - Older libraries might use a prefix 'Start' for LRO methods and may not include the `WaitUntil` parameter. ``` -------------------------------- ### Mocking ConfigurationClient with Moq in .NET Source: https://azure.github.io/azure-sdk/dotnet_/introduction This C# code demonstrates how to mock the `ConfigurationClient` using the Moq library. It sets up a mock response and configures the client's `Get` method to return a mocked `ConfigurationSetting`. This allows for non-live testing of components that depend on this client. ```csharp var mockResponse = new Mock(); var mock = new Mock(); mock.Setup(c => c.Get("Key", It.IsAny(), It.IsAny(), It.IsAny())) .Returns(new Response(mockResponse.Object, ConfigurationModelFactory.ConfigurationSetting("Key", "Value"))); ConfigurationClient client = mock.Object; ConfigurationSetting setting = client.Get("Key"); Assert.AreEqual("Value", setting.Value); ``` -------------------------------- ### C# Namespace Organization Example Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates organizing model types into a '_Models' subnamespace within a C# project to maintain a clean main namespace, as seen in Azure.Storage.Blobs. ```csharp namespace Azure.Storage.Blobs { public class BlobClient { ... } public class BlobClientOptions { ... } ... } namespace Azure.Storage.Blobs.Models { ... public class BlobContainerItem { ... } public class BlobContainerProperties { ...} ... } ``` -------------------------------- ### Custom LRO Implementation and Client Method Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates a custom LRO implementation (`CopyFromUriOperation`) inheriting from `Operation`, and a `BlobBaseClient` method (`CopyFromUri`) that initiates this LRO. This shows the pattern for creating and starting long-running operations. ```csharp public class CopyFromUriOperation : Operation { public CopyFromUriOperation(string id, BlobBaseClient client); ... } public class BlobBaseClient { public virtual CopyFromUriOperation CopyFromUri(WaitUntil wait, ..., CancellationToken cancellationToken = default); public virtual Task CopyFromUriAsync(WaitUntil wait, ..., CancellationToken cancellationToken = default); } ``` -------------------------------- ### Azure SDK EventSource Naming and GUID Verification Test Source: https://azure.github.io/azure-sdk/dotnet_/implementation This unit test verifies that the AzureCoreEventSource class correctly matches its expected name ('Azure-Core') and GUID. It also asserts that the event manifest can be generated, ensuring the EventSource is properly defined. This test helps maintain consistency and correctness in logging instrumentation. ```csharp [Test] public void MatchesNameAndGuid() { // Arrange & Act Type eventSourceType = typeof(AzureCoreEventSource); // Assert Assert.NotNull(eventSourceType); Assert.AreEqual("Azure-Core", EventSource.GetName(eventSourceType)); Assert.AreEqual(Guid.Parse("1015ab6c-4cd8-53d6-aec3-9b937011fa95"), EventSource.GetGuid(eventSourceType)); Assert.IsNotEmpty(EventSource.GenerateManifest(eventSourceType, "assemblyPathToIncludeInManifest")); } ``` -------------------------------- ### Implement Service Call with HttpPipeline in C# Source: https://azure.github.io/azure-sdk/dotnet_/implementation Demonstrates how to use HttpPipeline to implement a service call method in C#. The HttpPipeline handles common HTTP requirements like user agent, logging, distributed tracing, retries, and proxy configuration. This example shows setting the request method, URI, headers, content, and sending the request asynchronously. ```csharp public virtual async Task> AddAsync(ConfigurationSetting setting, CancellationToken cancellationToken = default) { if (setting == null) throw new ArgumentNullException(nameof(setting)); // validate other preconditions // Use HttpPipeline _pipeline filed of the client type to create new HTTP request using (Request request = _pipeline.CreateRequest()) { // specify HTTP request line request.Method = RequestMethod.Put; request.Uri.Reset(_endpoint); request.Uri.AppendPath(KvRoute, escape: false); requast.Uri.AppendPath(key); // add headers request.Headers.Add(IfNoneMatchWildcard); request.Headers.Add(MediaTypeKeyValueApplicationHeader); request.Headers.Add(HttpHeader.Common.JsonContentType); request.Headers.Add(HttpHeader.Common.CreateContentLength(content.Length)); // add content ReadOnlyMemory content = Serialize(setting); request.Content = HttpPipelineRequestContent.Create(content); // send the request Response response = await Pipeline.SendRequestAsync(request).ConfigureAwait(false); if (response.Status == 200) { // deserialize content Response result = await CreateResponse(response, cancellationToken); } else { throw new RequestFailedException(response); } } } ``` -------------------------------- ### ServiceBusSender Subclient Example (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates a `ServiceBusSender` subclient, which groups operations related to sending messages to a specific Azure Service Bus entity. It highlights properties that identify the entity and methods for sending and scheduling messages. ```csharp public class ServiceBusSender { protected ServiceBusSender(); public virtual string EntityPath { get; } public virtual Task CancelScheduledMessageAsync(long sequenceNumber, CancellationToken cancellationToken = default); public virtual ValueTask CreateMessageBatchAsync(CancellationToken cancellationToken = default); public virtual Task ScheduleMessageAsync(ServiceBusMessage message, DateTimeOffset scheduledEnqueueTime, CancellationToken cancellationToken = default); public virtual Task SendMessageAsync(ServiceBusMessage message, CancellationToken cancellationToken = default); // ... } ``` -------------------------------- ### Sample AzureCoreEventSource Declaration Source: https://azure.github.io/azure-sdk/dotnet_/implementation This C# code demonstrates a typical EventSource declaration for the Azure SDK. It includes defining event IDs, a singleton instance, and methods for logging specific events like 'MessageSent' and 'ClientClosing'. The example highlights checking 'IsEnabled' before performing expensive operations and using `WriteEvent` to log event data. ```csharp [EventSource(Name = EventSourceName)] internal sealed class AzureCoreEventSource : AzureEventSource { private const string EventSourceName = "Azure-Core"; // Having event ids defined as const makes it easy to keep track of them private const int MessageSentEventId = 0; private const int ClientClosingEventId = 1; public static AzureCoreEventSource Shared { get; } = new AzureCoreEventSource(); private AzureCoreEventSource() : base(EventSourceName) { } [NonEvent] public void MessageSent(Guid clientId, string messageBody) { // We are calling Guid.ToString make sure anyone is listening before spending resources if (IsEnabled(EventLevel.Informational, EventKeywords.None)) { MessageSent(clientId.ToString("N"), messageBody); } } // In this example we don't do any expensive parameter formatting so we can avoid extra method and IsEnabled check [Event(ClientClosingEventId, Level = EventLevel.Informational, Message = "Client {0} is closing the connection.")] public void ClientClosing(string clientId) { WriteEvent(ClientClosingEventId, clientId); } [Event(MessageSentEventId, Level = EventLevel.Informational, Message = "Client {0} sent message with body '{1}'")] private void MessageSent(string clientId, string messageBody) { WriteEvent(MessageSentEventId, clientId, messageBody); } } ``` -------------------------------- ### Hiding Older Overloads for Model Factory Methods in .NET Source: https://azure.github.io/azure-sdk/dotnet_/introduction This C# example demonstrates how to handle API evolution in Azure SDK .NET model factories. It shows the use of the `EditorBrowsableState.Never` attribute to hide older overloads when new ones are introduced with additional optional parameters, preventing ambiguity during mocking and client usage. ```csharp public static class ConfigurationModelFactory { [EditorBrowsable(EditorBrowsableState.Never)] public static ConfigurationSetting ConfigurationSetting(string key, string value, string label, string contentType, ETag eTag, DateTimeOffset? lastModified, bool? locked) => ConfigurationSetting(key, value, label, contentType, eTag, lastModified, locked, default); public static ConfigurationSetting ConfigurationSetting(string key, string value, string label=default, string contentType=default, ETag eTag=default, DateTimeOffset? lastModified=default, bool? locked=default, int? ttl=default); } ``` -------------------------------- ### Minimal Service Client Constructor (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates the recommended minimal constructor for a service client, requiring only essential parameters for service connection, such as a connection string. ```csharp public class ConfigurationClient { public ConfigurationClient(string connectionString); } ``` -------------------------------- ### Azure App Configuration Client Creation (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates how to create a ConfigurationClient using a connection string. This is a foundational step for interacting with Azure App Configuration services. Assumes a valid connection string is provided. ```csharp var client = new ConfigurationClient(connectionString); ``` -------------------------------- ### Service Client Constructor with Options (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates providing constructor overloads that accept a custom options object (e.g., ConfigurationClientOptions) for specifying advanced configurations like credentials or HTTP pipelines. ```csharp // options for configuring ConfigurationClient public class ConfigurationClientOptions : ClientOptions { ... } public class ConfigurationClient { public ConfigurationClient(string connectionString, ConfigurationClientOptions options); ... } ``` -------------------------------- ### Mocking Recommendations for Azure SDK .NET Libraries Source: https://azure.github.io/azure-sdk/dotnet_/introduction These C# code snippets illustrate key recommendations for making Azure SDK .NET libraries mockable. They show how to implement virtual properties and methods, including those returning other client types, to facilitate mocking with libraries like Moq. ```csharp public class BlobContainerClient { public virtual string Name { get; } public virtual Uri Uri { get; } } ``` ```csharp public class BlobContainerClient { public virtual BlobClient GetBlobClient(); } ``` ```csharp public class BlobContainerClient { // This method is possible to mock public virtual AppendBlobClient GetAppendBlobClient() {} } public class BlobContainerClientExtensions { // This method is impossible to mock public static AppendBlobClient GetAppendBlobClient(this BlobContainerClient containerClient) {} } ``` -------------------------------- ### Service Client Constructors with Overloads (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Shows a service client with multiple constructor overloads, including one with a connection string, another with connection string and options, and a third with a URI, credential, and options. ```csharp public class ConfigurationClient { public ConfigurationClient(string connectionString); public ConfigurationClient(string connectionString, ConfigurationClientOptions options); public ConfigurationClient(Uri uri, TokenCredential credential, ConfigurationClientOptions options = default); } ``` -------------------------------- ### Method Naming Conventions Source: https://azure.github.io/azure-sdk/dotnet_/introduction Standard verbs should be used for methods that access or manipulate server resources. This section outlines the recommended verbs, their parameters, return types, and comments. ```APIDOC ## Method Naming Conventions ### Description Methods accessing or manipulating server resources should follow standard .NET naming conventions, with specific verbs for common operations. ### Verbs and Usage * **Create** * **Parameters**: `key`, `item` * **Returns**: `Created item` * **Comments**: Creates a resource. Throws if the resource exists. * **Set** * **Parameters**: `key`, `item` * **Returns**: (None) * **Comments**: Creates or replaces a resource. * **Update** * **Parameters**: `key`, `item` * **Returns**: `item` * **Comments**: Updates a resource. Throws if the resource does not exist. May take a parameter to control update semantics (replace, merge, etc.). * **Get** * **Parameters**: `key` * **Returns**: `item` * **Comments**: Retrieves a resource. Throws if the resource does not exist. * **Get** * **Parameters**: `key`, `item` * **Returns**: `item` * **Comments**: Retrieves one or more resources. Returns an empty set if no resources are found. * **Delete** * **Parameters**: `item` * **Returns**: `item` * **Comments**: Deletes one or more resources, or is a no-op if the resources do not exist. * **Remove** * **Parameters**: `index`, `item` * **Returns**: `item` * **Comments**: Removes a reference to a resource from a collection. Does not delete the actual resource, only the reference. * **Exists** * **Parameters**: `key` * **Returns**: `item` (boolean) * **Comments**: Returns `true` if the resource exists, otherwise returns `false`. ``` -------------------------------- ### Constructing Azure Service Clients (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates common constructor patterns for creating service clients, including simple and advanced constructors that accept binding parameters for service endpoint and authentication credentials. These constructors are essential for invoking service operations. ```csharp public Client(); public Client(, ClientOptions options); public Client(, ClientOptions options = default); ``` ```csharp // hello world constructors using the main authentication method on the service's Azure Portal (typically a connection string) // we don't want to use default parameters here; all other overloads can use default parameters public BlobServiceClient(string connectionString) public BlobServiceClient(string connectionString, BlobClientOptions options) // anonymous access public BlobServiceClient(Uri uri, BlobClientOptions options = default) // using credential types public BlobServiceClient(Uri uri, StorageSharedKeyCredential credential, BlobClientOptions options = default) public BlobServiceClient(Uri uri, TokenCredential credential, BlobClientOptions options = default) ``` -------------------------------- ### Avoid Virtual Property References in Client Constructors (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction This example illustrates a scenario to avoid: referencing virtual properties of a client class within its own constructor. This practice can lead to issues in .NET's constructor design, as the underlying fields might not be initialized or mocked properties might not be set up correctly. It suggests using parameters or local variables as alternatives. ```csharp public class ConfigurationClient { private readonly ConfigurationRestClient _client; public ConfigurationClient(string connectionString) { ConnectionString = connectionString; // Use parameter below instead of the class-defined virtual property. _client = new ConfigurationRestClient(connectionString); } public virtual string ConnectionString { get; } ``` -------------------------------- ### Azure SDK for .NET: Options Pattern Convenience Overloads Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates the use of convenience overloads for complex service methods in the Azure SDK for .NET, allowing users to call methods with a subset of parameters from the main Options bag. This improves developer experience for common scenarios. ```csharp // main overload taking the options property bag public virtual Response CreateBlob(BlobCreateOptions options = null, CancellationToken cancellationToken = default); // simple overload with a subset of parameters of the options bag public virtual Response CreateBlob(string blobName, CancellationToken cancellationToken = default); } ``` -------------------------------- ### Azure SDK for .NET: Simple vs. Complex Service Methods Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates the design of simple and complex service methods using C# in the Azure SDK for .NET. Simple methods have fewer, primitive parameters, while complex methods use an Options class for numerous parameters, with convenience overloads provided. ```csharp public class BlobContainerClient { // simple service method public virtual Response UploadBlob(string blobName, Stream content, CancellationToken cancellationToken = default); // complex service method public virtual Response CreateBlob(BlobCreateOptions options = null, CancellationToken cancellationToken = default); // convinience overload[s] public virtual Response CreateBlob(string blobName, CancellationToken cancellationToken = default); } public class BlobCreateOptions { public PublicAccessType Access { get; set; } public IDictionary Metadata { get; } public BlobContainerEncryptionScopeOptions Encryption { get; set; } ... } ``` -------------------------------- ### Azure SDK for .NET: Methods Returning Collections (Paging) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Shows how methods returning collections of data in batches or pages are exposed in the Azure SDK for .NET. It uses `Pageable` for synchronous operations and `AsyncPageable` for asynchronous operations, both found in the `Azure.Core` package. ```csharp public class ConfigurationClient { // asynchronous API returning a collection of items public virtual AsyncPageable> GetConfigurationSettingsAsync(...); // synchronous variant of the method above public virtual Pageable GetConfigurationSettings(...); ... } ``` -------------------------------- ### General Azure SDK Service Client Structure (.NET) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Defines the standard structure for a .NET Azure SDK service client, including constructors, service methods (synchronous and asynchronous), and options classes. It emphasizes immutability and clear naming conventions. ```csharp namespace Azure.. { // main service client class public class Client { // simple constructors; don't use default parameters public Client(); public Client(, ClientOptions options); // 0 or more advanced constructors public Client(, ClientOptions options = default); // mocking constructor protected Client(); // service methods (synchronous and asynchronous) public virtual Task> Async(, CancellationToken cancellationToken = default); public virtual Response (, CancellationToken cancellationToken = default); // other members } // options for configuring the client public class ClientOptions : ClientOptions { } } ``` -------------------------------- ### Add ConfigurationClient for ASP.NET Core DI Source: https://azure.github.io/azure-sdk/dotnet_/implementation Provides an extension method to register ConfigurationClient with ASP.NET Core's Dependency Injection container using a connection string. It utilizes IAzureClientFactoryBuilder to manage client registration. ```csharp public static IAzureClientBuilder AddConfigurationClient(this TBuilder builder, string connectionString) where TBuilder : IAzureClientFactoryBuilder { return builder.RegisterClientFactory(options => new ConfigurationClient(connectionString, options)); } ``` -------------------------------- ### Provide Protected Parameterless Constructor for Mocking (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction This code snippet demonstrates the recommended practice of including a protected, parameterless constructor in a client class. This facilitates mocking by allowing derived classes or mocking frameworks to instantiate the client without needing to provide actual constructor arguments. ```csharp public class ConfigurationClient { protected ConfigurationClient(); } ``` -------------------------------- ### Mocking Support Source: https://azure.github.io/azure-sdk/dotnet_/introduction Service methods should be declared as virtual to facilitate mocking and testing. ```APIDOC ## Mocking Support ### Description To enable mocking for testing purposes, service methods should be virtual. ### Requirement * **Virtual Methods**: All service methods intended for use in scenarios requiring mocking should be declared as `virtual`. ``` -------------------------------- ### Azure Storage Blob Hierarchy Clients Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates the hierarchical relationship between Azure Storage clients: BlobServiceClient, BlobContainerClient, and BlobClient. Includes methods for navigating the hierarchy. ```csharp public class BlobServiceClient { // ... public virtual BlobContainerClient GetBlobContainerClient(string blobContainerName); // ... } public class BlobContainerClient { // ... public virtual BlobClient GetBlobClient(string blobName); // ... } public class BlobClient { // ... } ``` -------------------------------- ### Add SecretClient for ASP.NET Core DI with Configuration Source: https://azure.github.io/azure-sdk/dotnet_/implementation Provides an extension method to register SecretClient with ASP.NET Core's Dependency Injection container using IConfiguration. This allows for dynamic client creation based on configuration values. ```csharp public static IAzureClientBuilder AddSecretClient(this TBuilder builder, TConfiguration configuration) where TBuilder : IAzureClientFactoryBuilderWithConfiguration { return builder.RegisterClientFactory(configuration); } ``` -------------------------------- ### SDK Consumer: Using LROs with Azure SDK Source: https://azure.github.io/azure-sdk/dotnet_/introduction Demonstrates how an SDK consumer interacts with Long Running Operations. It shows three scenarios: automatic polling using `WaitUntil.Completed`, manual polling with status updates, and retrieving an operation ID to resume an LRO later. ```csharp BlobBaseClient client = ... // automatic polling { Operation operation = await client.CopyFromUri(WaitUntil.Completed, ...); Console.WriteLine(operation.Value); } // manual polling { CopyFromUriOperation operation = await client.CopyFromUriAsync(WaitUntil.Started, ...); while (true) { await operation.UpdateStatusAsync(); if (operation.HasCompleted) break; await Task.Delay(1000); // play some elevator music } if (operation.HasValue) Console.WriteLine(operation.Value); } // saving operation ID { CopyFromUriOperation operation = await client.CopyFromUriAsync(WaitUntil.Started, ...); string operationId = operation.Id; // two days later var operation2 = new CopyFromUriOperation(operationId, client); long value = await operation2.WaitForCompletionAsync(); } ``` -------------------------------- ### Creating Model Factory for Mocking in Azure SDK .NET Source: https://azure.github.io/azure-sdk/dotnet_/introduction This C# code defines a static factory class, `ConfigurationModelFactory`, intended for use with mocking Azure SDK .NET libraries. It provides static methods to construct model instances, which is crucial for mock implementations, especially when model types lack public constructors. ```csharp public static class ConfigurationModelFactory { public static ConfigurationSetting ConfigurationSetting(string key, string value, string label=default, string contentType=default, ETag eTag=default, DateTimeOffset? lastModified=default, bool? locked=default); public static SettingBatch SettingBatch(ConfigurationSetting[] settings, string link, SettingSelector selector); } ``` -------------------------------- ### Feature Detection with Nullable Types (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Illustrates how to handle features supported by specific service API versions using the _tester-doer_ pattern or nullable types, allowing consumers to conditionally use features like batch operations. ```csharp if (client.CanBatch) { Response response = await client.GetBatch("some_key*"); Guid? Guid = response.Result.Guid; } else { Response response1 = await client.GetAsync("some_key1"); Response response2 = await client.GetAsync("some_key2"); Response response3 = await client.GetAsync("some_key3"); } ``` -------------------------------- ### Return Types Source: https://azure.github.io/azure-sdk/dotnet_/introduction Defines the expected return types for synchronous and asynchronous methods, including handling of response content. ```APIDOC ## Return Types ### Description This section details the recommended return types for synchronous and asynchronous Azure SDK methods. ### Synchronous Methods * **Return Type**: `Response` or `Response`. * `T` represents the deserialized response content. ### Asynchronous Methods (Network Requests) * **Return Type**: `Task>` or `Task`. * `T` represents the deserialized response content. * `Task` is preferred over `ValueTask` for network requests. ### Response Content (`T`) The type `T` can represent either an unstructured payload or a structured model type: * **Unstructured Payloads**: * `System.IO.Stream`: For large payloads. * `byte[]`: For small payloads. * `ReadOnlyMemory`: For slices of small payloads. * **Structured Model Types**: * Use a model type if the response content has a schema and can be deserialized. Refer to 'Model Types' documentation for details. ``` -------------------------------- ### Add SecretClient for ASP.NET Core DI with TokenCredentials Source: https://azure.github.io/azure-sdk/dotnet_/implementation Provides an extension method to register SecretClient with ASP.NET Core's Dependency Injection container when TokenCredentials are required. It uses IAzureClientFactoryBuilderWithCredential to facilitate registration. ```csharp public static IAzureClientBuilder AddSecretClient(this TBuilder builder, Uri vaultUri) where TBuilder : IAzureClientFactoryBuilderWithCredential { return builder.RegisterClientFactory((options, cred) => new SecretClient(vaultUri, cred, options)); } ``` -------------------------------- ### Provide Protected Constructor for Mocking in Operation (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction This guideline specifies that subclasses of `Operation` should provide a protected parameterless constructor to facilitate mocking. This is crucial for unit testing scenarios where the operation's behavior needs to be simulated. ```csharp public class CopyFromUriOperation { protected CopyFromUriOperation(); } ``` -------------------------------- ### Write JSON using Utf8JsonWriter in C# Source: https://azure.github.io/azure-sdk/dotnet_/implementation Demonstrates how to write JSON payloads using `Utf8JsonWriter` for efficient JSON serialization in .NET. This is recommended for writing JSON content. ```csharp var json = new Utf8JsonWriter(writer); json.WriteStartObject(); json.WriteString("value", setting.Value); json.WriteString("content_type", setting.ContentType); json.WriteEndObject(); json.Flush(); written = (int)json.BytesWritten; ``` -------------------------------- ### Handle Operation Completion in Subtypes of Operation Source: https://azure.github.io/azure-sdk/dotnet_/implementation Implement `UpdateStatus` and `UpdateStatusAsync` in `Operation` subtypes. Check `HasCompleted` and return `GetRawResponse()` immediately if true. This optimizes scenarios where the operation might already be finished, especially in mocking. ```csharp public override Response UpdateStatus( CancellationToken cancellationToken = default) => UpdateStatusAsync(false, cancellationToken).EnsureCompleted(); public override async ValueTask UpdateStatusAsync( CancellationToken cancellationToken = default) => await UpdateStatusAsync(true, cancellationToken).ConfigureAwait(false); private async Task UpdateStatusAsync(bool async, CancellationToken cancellationToken) { // Short-circuit when already completed (which improves mocking scenarios that won't have a client). if (HasCompleted) { return GetRawResponse(); } // some service operation call here, which the above check avoids if the operation has already completed. ... } ``` -------------------------------- ### ClientOptions Subclass and ServiceVersion Enum (C#) Source: https://azure.github.io/azure-sdk/dotnet_/introduction Defines a subclass of ClientOptions named ConfigurationClientOptions, including a ServiceVersion enum for specifying the API version. It enforces that the default version is valid and throws an exception for unsupported versions. ```csharp public class ConfigurationClientOptions : ClientOptions { public ConfigurationClientOptions(ServiceVersion version = ServiceVersion.V2019_05_09) { if (version == default) throw new ArgumentException($"The service version {version} is not supported by this library."); } } public enum ServiceVersion { V2019_05_09 = 1, } ... } ```