From 2a7f088694acc982fb2499d8247ec17926fa7301 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 18 Jul 2023 14:59:51 -0500 Subject: [PATCH 01/19] Update Azure SDK DI doc for additional app builder --- docs/azure/sdk/dependency-injection.md | 112 ++++++++++++------ .../Directory.Packages.props | 15 +++ .../WebApplicationBuilder/Program.cs | 55 +++++++++ .../Properties/launchSettings.json | 41 +++++++ .../WebApplicationBuilder.csproj | 18 +++ .../appsettings.Development.json | 8 ++ .../WebApplicationBuilder/appsettings.json | 9 ++ 7 files changed, 222 insertions(+), 36 deletions(-) create mode 100644 docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props create mode 100644 docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs create mode 100644 docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Properties/launchSettings.json create mode 100644 docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/WebApplicationBuilder.csproj create mode 100644 docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.Development.json create mode 100644 docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 824654783f63d..13c18c7f19061 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -3,20 +3,30 @@ title: Dependency injection with the Azure SDK for .NET description: Learn how to use dependency injection with the Azure SDK for .NET client libraries. ms.topic: how-to ms.custom: devx-track-dotnet, engagement-fy23 -ms.date: 2/28/2023 +ms.date: 07/18/2023 --- # Dependency injection with the Azure SDK for .NET -This article demonstrates how to register Azure service clients from the [latest Azure SDKs for .NET](https://azure.github.io/azure-sdk/releases/latest/index.html#net) for [dependency injection in an ASP.NET Core app](/aspnet/core/fundamentals/dependency-injection). Every ASP.NET Core app starts up by using the instructions provided in the _Program.cs_ file. +This article demonstrates how to register Azure service clients from the [latest Azure client libraries for .NET](https://azure.github.io/azure-sdk/releases/latest/index.html#net) for [dependency injection in a .NET app](/dotnet/core/extensions/dependency-injection). Every modern .NET app starts up by using the instructions provided in a *Program.cs* file. -To configure the service clients, first add the following NuGet packages to your project: +## Install packages -- [Microsoft.Extensions.Azure](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/extensions/Microsoft.Extensions.Azure/README.md) -- [Azure.Identity](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/identity/Azure.Identity/README.md) -- The `Azure.*` package you'd like to use. +To register and configure service clients from an [`Azure.`-prefixed package](/dotnet/azure/sdk/packages#libraries-using-azurecore): -The sample code in this article uses Key Vault secrets and Blob Storage for demonstration purposes. +1. Install the [Microsoft.Extensions.Azure](https://www.nuget.org/packages/Microsoft.Extensions.Azure) package in your project: + + ```dotnetcli + dotnet add package Microsoft.Extensions.Azure + ``` + +1. Install the [Azure.Identity](https://www.nuget.org/packages/Azure.Identity) package to configure a `TokenCredential` type to use for authenticating all registered clients that accept such a type: + + ```dotnetcli + dotnet add package Azure.Identity + ``` + +For demonstration purposes, the sample code in this article uses the Key Vault Secrets and Blob Storage libraries. Install the following packages to follow along: ```dotnetcli dotnet add package Microsoft.Extensions.Azure @@ -25,34 +35,64 @@ dotnet add package Azure.Security.KeyVault.Secrets dotnet add package Azure.Storage.Blobs ``` -## Register client +## Register clients -In the _Program.cs_ file, register a client for each service: +In the *Program.cs* file, invoke the extension method to register a client for each service. See the following application builder-specific code samples for guidance. + +### [WebApplicationBuilder](#tab/web-app-builder) + +:::code language="csharp" source="snippets/dependency-injection/WebApplicationBuilder/Program.cs" id="snippet_WebApplicationBuilder" highlight="8-13"::: ```csharp +using Azure.Identity; +using Microsoft.Extensions.Azure; + +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + builder.Services.AddAzureClients(clientBuilder => { - // Add a KeyVault client clientBuilder.AddSecretClient(keyVaultUrl); - - // Add a Storage account client clientBuilder.AddBlobServiceClient(storageUrl); + clientBuilder.UseCredential(new DefaultAzureCredential()); +}); + +WebApplication app = builder.Build(); + +// code omitted for brevity + +app.Run(); +``` + +### [HostApplicationBuilder](#tab/host-app-builder) - // Use DefaultAzureCredential by default +```csharp +using Azure.Identity; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Hosting; + +HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); + +builder.Services.AddAzureClients(clientBuilder => +{ + clientBuilder.AddSecretClient(keyVaultUrl); + clientBuilder.AddBlobServiceClient(storageUrl); clientBuilder.UseCredential(new DefaultAzureCredential()); }); -builder.Services.AddControllers(); +// code omitted for brevity + +using IHost host = builder.Build(); +await host.RunAsync(); ``` In the preceding code: -* You specify the `Uri`-typed `keyVaultUrl` and `storageUrl` variables. The [Store configuration separately from code](#store-configuration-separately-from-code) section shows how you can avoid specifying the URLs explicitly. -* is used for authentication. `DefaultAzureCredential` chooses the best authentication mechanism based on your environment, allowing you to move your app seamlessly from development to production with no code changes. +* Key Vault Secrets and Blob Storage clients are registered using and , respectively. The `Uri`-typed `keyVaultUrl` and `storageUrl` arguments are passed. To avoid specifying the URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section. +* is used to satisfy the `TokenCredential` argument requirement for each registered client. When one of the clients is created, `DefaultAzureCredential` is used to authenticate. ## Use the registered clients -With the clients registered in the `AddAzureClients`, you can now use them: +With the clients registered via the method, you can now use them. In the following example, [constructor injection](/dotnet/core/extensions/dependency-injection#constructor-injection-behavior) is used to obtain the Blob Storage client in an ASP.NET Core API controller: ```csharp [ApiController] @@ -66,16 +106,18 @@ public class MyApiController : ControllerBase _blobServiceClient = blobServiceClient; } - // Get a list of all the blobs in the demo container [HttpGet] public async Task> Get() { - var containerClient = _blobServiceClient.GetBlobContainerClient("demo"); + BlobContainerClient containerClient = + _blobServiceClient.GetBlobContainerClient("demo"); var results = new List(); + await foreach (BlobItem blob in containerClient.GetBlobsAsync()) { results.Add(blob.Name); } + return results.ToArray(); } } @@ -83,7 +125,7 @@ public class MyApiController : ControllerBase ## Store configuration separately from code -In the [Register client](#register-client) section, you explicitly specify the `keyVaultUrl` and `storageUrl` variables. This approach could cause problems when you run code against different environments during development and production. The .NET team suggests [storing such configurations in environment-dependent JSON files](../../core/extensions/configuration-providers.md#json-configuration-provider). For example, you can have an _appsettings.Development.json_ file containing development environment settings. Another _appsettings.Production.json_ file would contain production environment settings, and so on. The file format is: +In the [Register clients](#register-clients) section, you explicitly specify the `keyVaultUrl` and `storageUrl` variables. This approach could cause problems when you run code against different environments during development and production. The .NET team suggests [storing such configurations in environment-dependent JSON files](../../core/extensions/configuration-providers.md#json-configuration-provider). For example, you can have an *appsettings.Development.json* file containing development environment settings. Another *appsettings.Production.json* file would contain production environment settings, and so on. The file format is: ```json { @@ -106,32 +148,30 @@ In the [Register client](#register-client) section, you explicitly specify the ` } ``` -You can add any options from into the JSON file's `AzureDefaults` section. One of the options is the retry policy. For more information, see [Configure a new retry policy](#configure-a-new-retry-policy). +You can add any properties from the class into the JSON file's `AzureDefaults` section. In the preceding JSON sample, the `AzureDefaults.Retry` object literal: + +* Represents the retry policy configuration settings. +* Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. + +For more information, see [Configure a new retry policy](#configure-a-new-retry-policy). Since the `Configuration` object is a member of the `builder` instance, you can configure secrets: ```csharp builder.Services.AddAzureClients(clientBuilder => { - // Add a KeyVault client clientBuilder.AddSecretClient(builder.Configuration.GetSection("KeyVault")); - - // Add a storage account client clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("Storage")); - - // Use DefaultAzureCredential by default clientBuilder.UseCredential(new DefaultAzureCredential()); // Set up any default settings clientBuilder.ConfigureDefaults(builder.Configuration.GetSection("AzureDefaults")); }); - -builder.Services.AddControllers(); ``` ## Configure multiple service clients with different names -Assume you have two storage accounts: one for private information and one for public information. Your app transfers data from the public to private storage account after some operation. You need to have two storage service clients. To set up these clients in the _Program.cs_ file: +Imagine you have two storage accounts: one for private information and another for public information. Your app transfers data from the public to the private storage account after some operation. You need to have two storage service clients. To differentiate those two clients, use the extension method: ```csharp builder.Services.AddAzureClients(clientBuilder => @@ -142,7 +182,7 @@ builder.Services.AddAzureClients(clientBuilder => }); ``` -In your controller, you can access the named service clients using : +Using an ASP.NET Core controller as an example, access the named service client using the interface: ```csharp public class HomeController : Controller @@ -164,7 +204,7 @@ The unnamed service client is still available in the same way as before. Named c ## Configure a new retry policy -At some point, you might want to change the default settings for a service client. You may want different retry settings or to use a different service API version, for example. You can set the retry settings globally or on a per-service basis. Assume you have the following _appsettings.json_ file: +At some point, you may want to change the default settings for a service client. For example, you may want different retry settings or to use a different service API version. You can set the retry settings globally or on a per-service basis. Assume you have the following *appsettings.json* file in your ASP.NET Core project: ```json { @@ -185,7 +225,7 @@ At some point, you might want to change the default settings for a service clien } ``` -You could change the retry policy depending on your needs like so: +You can change the retry policy depending on your needs like so: ```csharp builder.Services.AddAzureClients(clientBuilder => @@ -213,7 +253,7 @@ builder.Services.AddAzureClients(clientBuilder => }); ``` -You can also place policy overrides in the _appsettings.json_ file: +You can also place policy overrides in the *appsettings.json* file: ```json { @@ -228,6 +268,6 @@ You can also place policy overrides in the _appsettings.json_ file: ## See also -- [Dependency injection in .NET](../../core/extensions/dependency-injection.md) -- [Configuration in .NET](../../core/extensions/configuration.md) -- [Configuration in ASP.NET Core](/aspnet/core/fundamentals/configuration) +* [Dependency injection in ASP.NET Core](/aspnet/core/fundamentals/dependency-injection) +* [Configuration in .NET](/dotnet/core/extensions/configuration) +* [Configuration in ASP.NET Core](/aspnet/core/fundamentals/configuration) diff --git a/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props b/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props new file mode 100644 index 0000000000000..cc581cedbf0da --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props @@ -0,0 +1,15 @@ + + + true + + + + + + + + + + + + diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs new file mode 100644 index 0000000000000..1f5f339c7c3ca --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -0,0 +1,55 @@ +#region snippet_WebApplicationBuilder +using Azure.Identity; +using Microsoft.Extensions.Azure; + +var keyVaultUrl = new Uri(""); +var storageUrl = new Uri(""); +WebApplicationBuilder builder = WebApplication.CreateBuilder(args); + +builder.Services.AddAzureClients(clientBuilder => +{ + clientBuilder.AddSecretClient(keyVaultUrl); + clientBuilder.AddBlobServiceClient(storageUrl); + clientBuilder.UseCredential(new DefaultAzureCredential()); +}); + +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +WebApplication app = builder.Build(); +#endregion snippet_WebApplicationBuilder + +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +string[] summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/weatherforecast", () => +{ + WeatherForecast[] forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; +}) +.WithName("GetWeatherForecast") +.WithOpenApi(); + +await app.RunAsync(); + +internal record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Properties/launchSettings.json b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Properties/launchSettings.json new file mode 100644 index 0000000000000..0ee685fbc4f02 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:24340", + "sslPort": 44314 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5038", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7117;http://localhost:5038", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/WebApplicationBuilder.csproj b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/WebApplicationBuilder.csproj new file mode 100644 index 0000000000000..8c8344ce817d1 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/WebApplicationBuilder.csproj @@ -0,0 +1,18 @@ + + + + net7.0 + enable + enable + + + + + + + + + + + + diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.Development.json b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.Development.json new file mode 100644 index 0000000000000..0c208ae9181e5 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json new file mode 100644 index 0000000000000..10f68b8c8b4f7 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} From c428f6d0ed6d8048eaea5181df048dfd947d256f Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 18 Jul 2023 15:05:17 -0500 Subject: [PATCH 02/19] Update section link --- docs/azure/sdk/logging.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/logging.md b/docs/azure/sdk/logging.md index d911342905a26..839863a5f3e25 100644 --- a/docs/azure/sdk/logging.md +++ b/docs/azure/sdk/logging.md @@ -154,7 +154,7 @@ Using the Azure Service Bus library as an example, complete the following steps: ### Logging without client registration -There are scenarios in which [registering an Azure SDK library's client with the DI container](dependency-injection.md#register-client) is either impossible or unnecessary: +There are scenarios in which [registering an Azure SDK library's client with the DI container](dependency-injection.md#register-clients) is either impossible or unnecessary: - The Azure SDK library doesn't include an `IServiceCollection` extension method to register a client in the DI container. - Your app uses Azure extension libraries that depend on other Azure SDK libraries. Examples of such Azure extension libraries include: From 287495fcd00689ddcf5c91d38fa9d52d45c624bb Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 18 Jul 2023 15:11:58 -0500 Subject: [PATCH 03/19] Terminate tab group and fix code sample --- docs/azure/sdk/dependency-injection.md | 22 ++----------------- .../WebApplicationBuilder/Program.cs | 4 ++-- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 13c18c7f19061..3291b73c21d1d 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -43,26 +43,6 @@ In the *Program.cs* file, invoke the -{ - clientBuilder.AddSecretClient(keyVaultUrl); - clientBuilder.AddBlobServiceClient(storageUrl); - clientBuilder.UseCredential(new DefaultAzureCredential()); -}); - -WebApplication app = builder.Build(); - -// code omitted for brevity - -app.Run(); -``` - ### [HostApplicationBuilder](#tab/host-app-builder) ```csharp @@ -85,6 +65,8 @@ using IHost host = builder.Build(); await host.RunAsync(); ``` +--- + In the preceding code: * Key Vault Secrets and Blob Storage clients are registered using and , respectively. The `Uri`-typed `keyVaultUrl` and `storageUrl` arguments are passed. To avoid specifying the URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section. diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs index 1f5f339c7c3ca..b84ff818dc375 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -2,8 +2,8 @@ using Azure.Identity; using Microsoft.Extensions.Azure; -var keyVaultUrl = new Uri(""); -var storageUrl = new Uri(""); +var keyVaultUrl = new Uri(""); +var storageUrl = new Uri(""); WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.AddAzureClients(clientBuilder => From c40ecc1a7187bb2df26deffb52794796947f9fb3 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 09:25:07 -0500 Subject: [PATCH 04/19] More improvements --- docs/azure/sdk/dependency-injection.md | 45 ++----------------- .../Directory.Packages.props | 7 ++- .../HostApplicationBuilder.csproj | 17 +++++++ .../HostApplicationBuilder/Program.cs | 15 +++++++ .../WebApplicationBuilder/Program.cs | 6 +-- .../WebApplicationBuilder/appsettings.json | 16 +++++++ 6 files changed, 57 insertions(+), 49 deletions(-) create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/HostApplicationBuilder.csproj create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 3291b73c21d1d..8dd02b7e9fcd0 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -45,31 +45,13 @@ In the *Program.cs* file, invoke the -{ - clientBuilder.AddSecretClient(keyVaultUrl); - clientBuilder.AddBlobServiceClient(storageUrl); - clientBuilder.UseCredential(new DefaultAzureCredential()); -}); - -// code omitted for brevity - -using IHost host = builder.Build(); -await host.RunAsync(); -``` +:::code language="csharp" source="snippets/dependency-injection/HostApplicationBuilder/Program.cs" highlight="7-12"::: --- In the preceding code: -* Key Vault Secrets and Blob Storage clients are registered using and , respectively. The `Uri`-typed `keyVaultUrl` and `storageUrl` arguments are passed. To avoid specifying the URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section. +* Key Vault Secrets and Blob Storage clients are registered using and , respectively. The `Uri`-typed arguments are passed. To avoid specifying these URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section. * is used to satisfy the `TokenCredential` argument requirement for each registered client. When one of the clients is created, `DefaultAzureCredential` is used to authenticate. ## Use the registered clients @@ -107,28 +89,9 @@ public class MyApiController : ControllerBase ## Store configuration separately from code -In the [Register clients](#register-clients) section, you explicitly specify the `keyVaultUrl` and `storageUrl` variables. This approach could cause problems when you run code against different environments during development and production. The .NET team suggests [storing such configurations in environment-dependent JSON files](../../core/extensions/configuration-providers.md#json-configuration-provider). For example, you can have an *appsettings.Development.json* file containing development environment settings. Another *appsettings.Production.json* file would contain production environment settings, and so on. The file format is: +In the [Register clients](#register-clients) section, you explicitly passed the `Uri`-typed variables to the client constructors. This approach could cause problems when you run code against different environments during development and production. The .NET team suggests [storing such configurations in environment-dependent JSON files](../../core/extensions/configuration-providers.md#json-configuration-provider). For example, you can have an *appsettings.Development.json* file containing development environment settings. Another *appsettings.Production.json* file would contain production environment settings, and so on. The file format is: -```json -{ - "AzureDefaults": { - "Diagnostics": { - "IsTelemetryDisabled": false, - "IsLoggingContentEnabled": true - }, - "Retry": { - "MaxRetries": 3, - "Mode": "Exponential" - } - }, - "KeyVault": { - "VaultUri": "https://mykeyvault.vault.azure.net" - }, - "Storage": { - "ServiceUri": "https://mydemoaccount.storage.windows.net" - } -} -``` +:::code language="json" source="snippets/dependency-injection/WebApplicationBuilder/appsettings.json"::: You can add any properties from the class into the JSON file's `AzureDefaults` section. In the preceding JSON sample, the `AzureDefaults.Retry` object literal: diff --git a/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props b/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props index cc581cedbf0da..e0495eadc37f5 100644 --- a/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props +++ b/docs/azure/sdk/snippets/dependency-injection/Directory.Packages.props @@ -2,14 +2,13 @@ true - - + - + - + \ No newline at end of file diff --git a/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/HostApplicationBuilder.csproj b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/HostApplicationBuilder.csproj new file mode 100644 index 0000000000000..219deff185e56 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/HostApplicationBuilder.csproj @@ -0,0 +1,17 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + + + diff --git a/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs new file mode 100644 index 0000000000000..f5c8976d41b16 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs @@ -0,0 +1,15 @@ +using Azure.Identity; +using Microsoft.Extensions.Azure; +using Microsoft.Extensions.Hosting; + +HostApplicationBuilder builder = Host.CreateApplicationBuilder(args); + +builder.Services.AddAzureClients(clientBuilder => +{ + clientBuilder.AddSecretClient(new Uri("")); + clientBuilder.AddBlobServiceClient(new Uri("")); + clientBuilder.UseCredential(new DefaultAzureCredential()); +}); + +using IHost host = builder.Build(); +await host.RunAsync(); diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs index b84ff818dc375..9d839b0f5a3dc 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -2,14 +2,12 @@ using Azure.Identity; using Microsoft.Extensions.Azure; -var keyVaultUrl = new Uri(""); -var storageUrl = new Uri(""); WebApplicationBuilder builder = WebApplication.CreateBuilder(args); builder.Services.AddAzureClients(clientBuilder => { - clientBuilder.AddSecretClient(keyVaultUrl); - clientBuilder.AddBlobServiceClient(storageUrl); + clientBuilder.AddSecretClient(new Uri("")); + clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.UseCredential(new DefaultAzureCredential()); }); diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json index 10f68b8c8b4f7..c582b2771c531 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/appsettings.json @@ -1,4 +1,20 @@ { + "AzureDefaults": { + "Diagnostics": { + "IsTelemetryDisabled": false, + "IsLoggingContentEnabled": true + }, + "Retry": { + "MaxRetries": 3, + "Mode": "Exponential" + } + }, + "KeyVault": { + "VaultUri": "https://mykeyvault.vault.azure.net" + }, + "Storage": { + "ServiceUri": "https://mydemoaccount.storage.windows.net" + }, "Logging": { "LogLevel": { "Default": "Information", From c1824bf59c0d0a838ff7cdf7d02978a15ea204b8 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 09:29:58 -0500 Subject: [PATCH 05/19] Update line numbers --- docs/azure/sdk/dependency-injection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 8dd02b7e9fcd0..62005738c5c2f 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -41,7 +41,7 @@ In the *Program.cs* file, invoke the Date: Wed, 19 Jul 2023 11:02:18 -0500 Subject: [PATCH 06/19] Add HostBuilder code sample --- docs/azure/sdk/dependency-injection.md | 4 ++++ .../HostBuilder/HostBuilder.csproj | 17 ++++++++++++++++ .../HostBuilder/Program.cs | 20 +++++++++++++++++++ .../Properties/launchSettings.json | 11 ++++++++++ .../HostBuilder/Worker.cs | 20 +++++++++++++++++++ .../HostBuilder/appsettings.Development.json | 8 ++++++++ .../HostBuilder/appsettings.json | 8 ++++++++ 7 files changed, 88 insertions(+) create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostBuilder/HostBuilder.csproj create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostBuilder/Properties/launchSettings.json create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostBuilder/Worker.cs create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.Development.json create mode 100644 docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 62005738c5c2f..7d01f8cd10ee7 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -47,6 +47,10 @@ In the *Program.cs* file, invoke the + + + net7.0 + enable + enable + dotnet-HostBuilder-3f144e50-3cf7-463d-b3e7-33f5e9a62474 + + + + + + + + + + diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs new file mode 100644 index 0000000000000..eb0f8fc738161 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -0,0 +1,20 @@ +using HostBuilder; +#region snippet_HostBuilder +using Azure.Identity; +using Microsoft.Extensions.Azure; + +IHost host = Host.CreateDefaultBuilder(args) + .ConfigureServices(services => + { + services.AddHostedService(); + services.AddAzureClients(clientBuilder => + { + clientBuilder.AddSecretClient(new Uri("")); + clientBuilder.UseCredential(new DefaultAzureCredential()); + }); + }) + .Build(); + +host.Run(); +#endregion snippet_HostBuilder diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Properties/launchSettings.json b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Properties/launchSettings.json new file mode 100644 index 0000000000000..ca793456f2590 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "HostBuilder": { + "commandName": "Project", + "dotnetRunMessages": true, + "environmentVariables": { + "DOTNET_ENVIRONMENT": "Development" + } + } + } +} diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Worker.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Worker.cs new file mode 100644 index 0000000000000..a325a9cfe3086 --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Worker.cs @@ -0,0 +1,20 @@ +namespace HostBuilder; + +public class Worker : BackgroundService +{ + private readonly ILogger _logger; + + public Worker(ILogger logger) + { + _logger = logger; + } + + protected override async Task ExecuteAsync(CancellationToken stoppingToken) + { + while (!stoppingToken.IsCancellationRequested) + { + _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); + await Task.Delay(1000, stoppingToken); + } + } +} diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.Development.json b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.Development.json new file mode 100644 index 0000000000000..b2dcdb67421cd --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json new file mode 100644 index 0000000000000..b2dcdb67421cd --- /dev/null +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.Hosting.Lifetime": "Information" + } + } +} From 1a7bb630ee0903a83d7caf41904c8bbd422133dc Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 11:09:13 -0500 Subject: [PATCH 07/19] Update code sample --- .../sdk/snippets/dependency-injection/HostBuilder/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs index eb0f8fc738161..87e2e78887fbe 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -16,5 +16,5 @@ }) .Build(); -host.Run(); +await host.RunAsync(); #endregion snippet_HostBuilder From f1d94a17014f5601d62605c520d5191f83467c0f Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 13:00:47 -0500 Subject: [PATCH 08/19] More edits --- docs/azure/sdk/dependency-injection.md | 45 ++++++++++++++++++- .../HostBuilder/Program.cs | 2 +- .../HostBuilder/appsettings.json | 16 +++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 7d01f8cd10ee7..ef06855384292 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -37,7 +37,7 @@ dotnet add package Azure.Storage.Blobs ## Register clients -In the *Program.cs* file, invoke the extension method to register a client for each service. See the following application builder-specific code samples for guidance. +In the *Program.cs* file, invoke the extension method to register a client for each service. The following code samples provide guidance on application builders from the `Microsoft.AspNetCore.Builder` and `Microsoft.Extensions.Hosting` namespaces. ### [WebApplicationBuilder](#tab/web-app-builder) @@ -104,7 +104,23 @@ You can add any properties from the class into t For more information, see [Configure a new retry policy](#configure-a-new-retry-policy). -Since the `Configuration` object is a member of the `builder` instance, you can configure secrets: +The settings in the JSON configuration file can be retrieved using . + +### [WebApplicationBuilder](#tab/web-app-builder) + +```csharp +builder.Services.AddAzureClients(clientBuilder => +{ + clientBuilder.AddSecretClient(builder.Configuration.GetSection("KeyVault")); + clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("Storage")); + clientBuilder.UseCredential(new DefaultAzureCredential()); + + // Set up any default settings + clientBuilder.ConfigureDefaults(builder.Configuration.GetSection("AzureDefaults")); +}); +``` + +### [HostApplicationBuilder](#tab/host-app-builder) ```csharp builder.Services.AddAzureClients(clientBuilder => @@ -118,6 +134,31 @@ builder.Services.AddAzureClients(clientBuilder => }); ``` +### [HostBuilder](#tab/host-builder) + +```csharp +IHost host = Host.CreateDefaultBuilder(args) + .ConfigureServices((hostContext, services) => + { + services.AddHostedService(); + services.AddAzureClients(clientBuilder => + { + clientBuilder.AddSecretClient( + hostContext.Configuration.GetSection("KeyVault")); + clientBuilder.AddBlobServiceClient( + hostContext.Configuration.GetSection("Storage")); + clientBuilder.UseCredential(new DefaultAzureCredential()); + + // Set up any default settings + clientBuilder.ConfigureDefaults( + hostContext.Configuration.GetSection("AzureDefaults")); + }); + }) + .Build(); +``` + +--- + ## Configure multiple service clients with different names Imagine you have two storage accounts: one for private information and another for public information. Your app transfers data from the public to the private storage account after some operation. You need to have two storage service clients. To differentiate those two clients, use the extension method: diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs index 87e2e78887fbe..5d1946a8b267c 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -9,7 +9,7 @@ services.AddHostedService(); services.AddAzureClients(clientBuilder => { - clientBuilder.AddSecretClient(new Uri("")); clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.UseCredential(new DefaultAzureCredential()); }); diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json index b2dcdb67421cd..60e90a1f265d7 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/appsettings.json @@ -1,4 +1,20 @@ { + "AzureDefaults": { + "Diagnostics": { + "IsTelemetryDisabled": false, + "IsLoggingContentEnabled": true + }, + "Retry": { + "MaxRetries": 3, + "Mode": "Exponential" + } + }, + "KeyVault": { + "VaultUri": "https://mykeyvault.vault.azure.net" + }, + "Storage": { + "ServiceUri": "https://mydemoaccount.storage.windows.net" + }, "Logging": { "LogLevel": { "Default": "Information", From 9469d764b42c72a27e56dc16e6625eff3814f794 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 13:04:32 -0500 Subject: [PATCH 09/19] Update JSON sample --- docs/azure/sdk/dependency-injection.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index ef06855384292..accfb136a50a9 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -95,7 +95,26 @@ public class MyApiController : ControllerBase In the [Register clients](#register-clients) section, you explicitly passed the `Uri`-typed variables to the client constructors. This approach could cause problems when you run code against different environments during development and production. The .NET team suggests [storing such configurations in environment-dependent JSON files](../../core/extensions/configuration-providers.md#json-configuration-provider). For example, you can have an *appsettings.Development.json* file containing development environment settings. Another *appsettings.Production.json* file would contain production environment settings, and so on. The file format is: -:::code language="json" source="snippets/dependency-injection/WebApplicationBuilder/appsettings.json"::: +```json +{ + "AzureDefaults": { + "Diagnostics": { + "IsTelemetryDisabled": false, + "IsLoggingContentEnabled": true + }, + "Retry": { + "MaxRetries": 3, + "Mode": "Exponential" + } + }, + "KeyVault": { + "VaultUri": "https://mykeyvault.vault.azure.net" + }, + "Storage": { + "ServiceUri": "https://mydemoaccount.storage.windows.net" + } +} +``` You can add any properties from the class into the JSON file's `AzureDefaults` section. In the preceding JSON sample, the `AzureDefaults.Retry` object literal: From 059bbcc65a9e77116bfe9390c87bcaae1eaaec4e Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 13:14:26 -0500 Subject: [PATCH 10/19] Code formatting to prevent horizontal scrolling --- docs/azure/sdk/dependency-injection.md | 37 +++++++++++++++++++------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index accfb136a50a9..9d1b959455322 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -130,8 +130,12 @@ The settings in the JSON configuration file can be retrieved using { - clientBuilder.AddSecretClient(builder.Configuration.GetSection("KeyVault")); - clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("Storage")); + clientBuilder.AddSecretClient( + builder.Configuration.GetSection("KeyVault")); + + clientBuilder.AddBlobServiceClient( + builder.Configuration.GetSection("Storage")); + clientBuilder.UseCredential(new DefaultAzureCredential()); // Set up any default settings @@ -144,8 +148,12 @@ builder.Services.AddAzureClients(clientBuilder => ```csharp builder.Services.AddAzureClients(clientBuilder => { - clientBuilder.AddSecretClient(builder.Configuration.GetSection("KeyVault")); - clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("Storage")); + clientBuilder.AddSecretClient( + builder.Configuration.GetSection("KeyVault")); + + clientBuilder.AddBlobServiceClient( + builder.Configuration.GetSection("Storage")); + clientBuilder.UseCredential(new DefaultAzureCredential()); // Set up any default settings @@ -164,8 +172,10 @@ IHost host = Host.CreateDefaultBuilder(args) { clientBuilder.AddSecretClient( hostContext.Configuration.GetSection("KeyVault")); + clientBuilder.AddBlobServiceClient( hostContext.Configuration.GetSection("Storage")); + clientBuilder.UseCredential(new DefaultAzureCredential()); // Set up any default settings @@ -185,8 +195,11 @@ Imagine you have two storage accounts: one for private information and another f ```csharp builder.Services.AddAzureClients(clientBuilder => { - clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("PublicStorage")); - clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("PrivateStorage")) + clientBuilder.AddBlobServiceClient( + builder.Configuration.GetSection("PublicStorage")); + + clientBuilder.AddBlobServiceClient( + builder.Configuration.GetSection("PrivateStorage")) .WithName("PrivateStorage"); }); ``` @@ -240,18 +253,22 @@ You can change the retry policy depending on your needs like so: builder.Services.AddAzureClients(clientBuilder => { // Establish the global defaults - clientBuilder.ConfigureDefaults(builder.Configuration.GetSection("AzureDefaults")); + clientBuilder.ConfigureDefaults( + builder.Configuration.GetSection("AzureDefaults")); clientBuilder.UseCredential(new DefaultAzureCredential()); // A Key Vault Secrets client using the global defaults - clientBuilder.AddSecretClient(builder.Configuration.GetSection("KeyVault")); + clientBuilder.AddSecretClient( + builder.Configuration.GetSection("KeyVault")); // A Storage client with a custom retry policy - clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("Storage")) + clientBuilder.AddBlobServiceClient( + builder.Configuration.GetSection("Storage")) .ConfigureOptions(options => options.Retry.MaxRetries = 10); // A named storage client with a different custom retry policy - clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("CustomStorage")) + clientBuilder.AddBlobServiceClient( + builder.Configuration.GetSection("CustomStorage")) .WithName("CustomStorage") .ConfigureOptions(options => { From c5216ec88a57837a69ce8a77c5be5a0740e09c79 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 13:18:34 -0500 Subject: [PATCH 11/19] Link to client registration section --- docs/azure/sdk/dependency-injection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 9d1b959455322..952c5b6bd9baa 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -60,7 +60,7 @@ In the preceding code: ## Use the registered clients -With the clients registered via the method, you can now use them. In the following example, [constructor injection](/dotnet/core/extensions/dependency-injection#constructor-injection-behavior) is used to obtain the Blob Storage client in an ASP.NET Core API controller: +With the clients registered, as described in the [Register clients](#register-clients) section, you can now use them. In the following example, [constructor injection](/dotnet/core/extensions/dependency-injection#constructor-injection-behavior) is used to obtain the Blob Storage client in an ASP.NET Core API controller: ```csharp [ApiController] From fff26bb496723437d41318c74acbf906e60f6960 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 13:22:47 -0500 Subject: [PATCH 12/19] Wrap long lines of code --- docs/azure/sdk/dependency-injection.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 952c5b6bd9baa..4437c2e030b56 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -139,7 +139,8 @@ builder.Services.AddAzureClients(clientBuilder => clientBuilder.UseCredential(new DefaultAzureCredential()); // Set up any default settings - clientBuilder.ConfigureDefaults(builder.Configuration.GetSection("AzureDefaults")); + clientBuilder.ConfigureDefaults( + builder.Configuration.GetSection("AzureDefaults")); }); ``` @@ -157,7 +158,8 @@ builder.Services.AddAzureClients(clientBuilder => clientBuilder.UseCredential(new DefaultAzureCredential()); // Set up any default settings - clientBuilder.ConfigureDefaults(builder.Configuration.GetSection("AzureDefaults")); + clientBuilder.ConfigureDefaults( + builder.Configuration.GetSection("AzureDefaults")); }); ``` From 992ff048d2616e8ea95fbb6a8da671513cbc6d1f Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Wed, 19 Jul 2023 13:38:37 -0500 Subject: [PATCH 13/19] Shorten API xref link --- docs/azure/sdk/dependency-injection.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 4437c2e030b56..67cb9f19990ee 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -206,7 +206,7 @@ builder.Services.AddAzureClients(clientBuilder => }); ``` -Using an ASP.NET Core controller as an example, access the named service client using the interface: +Using an ASP.NET Core controller as an example, access the named service client using the interface: ```csharp public class HomeController : Controller @@ -249,7 +249,7 @@ At some point, you may want to change the default settings for a service client. } ``` -You can change the retry policy depending on your needs like so: +You can change the retry policy to suit your needs like so: ```csharp builder.Services.AddAzureClients(clientBuilder => @@ -263,7 +263,7 @@ builder.Services.AddAzureClients(clientBuilder => clientBuilder.AddSecretClient( builder.Configuration.GetSection("KeyVault")); - // A Storage client with a custom retry policy + // A Blob Storage client with a custom retry policy clientBuilder.AddBlobServiceClient( builder.Configuration.GetSection("Storage")) .ConfigureOptions(options => options.Retry.MaxRetries = 10); @@ -281,7 +281,7 @@ builder.Services.AddAzureClients(clientBuilder => }); ``` -You can also place policy overrides in the *appsettings.json* file: +You can also place retry policy overrides in the *appsettings.json* file: ```json { From bd38c7aac184374abcc66cf8f4cbf089bf43ea6f Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Fri, 21 Jul 2023 15:55:13 -0500 Subject: [PATCH 14/19] Remove duplicate package install commands --- docs/azure/sdk/dependency-injection.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 67cb9f19990ee..35635c107e0ce 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -3,7 +3,7 @@ title: Dependency injection with the Azure SDK for .NET description: Learn how to use dependency injection with the Azure SDK for .NET client libraries. ms.topic: how-to ms.custom: devx-track-dotnet, engagement-fy23 -ms.date: 07/18/2023 +ms.date: 07/21/2023 --- # Dependency injection with the Azure SDK for .NET @@ -29,8 +29,6 @@ To register and configure service clients from an [`Azure.`-prefixed package](/d For demonstration purposes, the sample code in this article uses the Key Vault Secrets and Blob Storage libraries. Install the following packages to follow along: ```dotnetcli -dotnet add package Microsoft.Extensions.Azure -dotnet add package Azure.Identity dotnet add package Azure.Security.KeyVault.Secrets dotnet add package Azure.Storage.Blobs ``` From e6522d999edef2bbe476cf50b87e9b0348c0b522 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 25 Jul 2023 12:01:25 -0500 Subject: [PATCH 15/19] Add explanation of AzureDefaults section name --- docs/azure/sdk/dependency-injection.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 35635c107e0ce..0c28d265ff118 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -114,10 +114,12 @@ In the [Register clients](#register-clients) section, you explicitly passed the } ``` -You can add any properties from the class into the JSON file's `AzureDefaults` section. In the preceding JSON sample, the `AzureDefaults.Retry` object literal: +You can add any properties from the class into the JSON file. In the preceding JSON sample: -* Represents the retry policy configuration settings. -* Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. +* The `AzureDefaults` section name is used; however, that name is arbitrary. +* The `AzureDefaults.Retry` object literal: + * Represents the retry policy configuration settings. + * Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. For more information, see [Configure a new retry policy](#configure-a-new-retry-policy). From 553721768b6812495d0087db355e6293da1c2555 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 25 Jul 2023 13:37:31 -0500 Subject: [PATCH 16/19] React to Alex's feedback --- docs/azure/sdk/dependency-injection.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 0c28d265ff118..f7f337524e06a 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -116,12 +116,12 @@ In the [Register clients](#register-clients) section, you explicitly passed the You can add any properties from the class into the JSON file. In the preceding JSON sample: -* The `AzureDefaults` section name is used; however, that name is arbitrary. +* The top-level key names, `AzureDefaults`, `KeyVault`, and `Storage`, are arbitrary. All other key names hold significance, and JSON serialization is performed in a case-insensitive manner. * The `AzureDefaults.Retry` object literal: - * Represents the retry policy configuration settings. + * Represents the [retry policy configuration settings](#configure-a-new-retry-policy). * Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. - -For more information, see [Configure a new retry policy](#configure-a-new-retry-policy). +* The `KeyVault:VaultUri` key's value maps to the `Uri`-typed argument of the constructor overload. +* The `Storage:ServiceUri` key's value maps to the `Uri`-typed argument of the constructor overload. The settings in the JSON configuration file can be retrieved using . From 15d3904e573ec7a97bf4ad552abf9d47c7a9ed67 Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 25 Jul 2023 13:51:39 -0500 Subject: [PATCH 17/19] Update verbiage --- docs/azure/sdk/dependency-injection.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index f7f337524e06a..299f3dd52bf74 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -120,8 +120,7 @@ You can add any properties from the class into t * The `AzureDefaults.Retry` object literal: * Represents the [retry policy configuration settings](#configure-a-new-retry-policy). * Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. -* The `KeyVault:VaultUri` key's value maps to the `Uri`-typed argument of the constructor overload. -* The `Storage:ServiceUri` key's value maps to the `Uri`-typed argument of the constructor overload. +* The `KeyVault:VaultUri` and `Storage:ServiceUri` key values map to the `Uri`-typed arguments of the and constructor overloads, respectively. The settings in the JSON configuration file can be retrieved using . From b58bec7a14795bb327893e71a2d0608271a0560e Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 25 Jul 2023 14:00:04 -0500 Subject: [PATCH 18/19] Add more clarity --- docs/azure/sdk/dependency-injection.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 299f3dd52bf74..70b51a0ada23d 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -114,15 +114,7 @@ In the [Register clients](#register-clients) section, you explicitly passed the } ``` -You can add any properties from the class into the JSON file. In the preceding JSON sample: - -* The top-level key names, `AzureDefaults`, `KeyVault`, and `Storage`, are arbitrary. All other key names hold significance, and JSON serialization is performed in a case-insensitive manner. -* The `AzureDefaults.Retry` object literal: - * Represents the [retry policy configuration settings](#configure-a-new-retry-policy). - * Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. -* The `KeyVault:VaultUri` and `Storage:ServiceUri` key values map to the `Uri`-typed arguments of the and constructor overloads, respectively. - -The settings in the JSON configuration file can be retrieved using . +You can add any properties from the class into the JSON file. The settings in the JSON configuration file can be retrieved using . ### [WebApplicationBuilder](#tab/web-app-builder) @@ -189,6 +181,14 @@ IHost host = Host.CreateDefaultBuilder(args) --- +In the preceding JSON sample: + +* The top-level key names, `AzureDefaults`, `KeyVault`, and `Storage`, are arbitrary. All other key names hold significance, and JSON serialization is performed in a case-insensitive manner. +* The `AzureDefaults.Retry` object literal: + * Represents the [retry policy configuration settings](#configure-a-new-retry-policy). + * Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. +* The `KeyVault:VaultUri` and `Storage:ServiceUri` key values map to the `Uri`-typed arguments of the and constructor overloads, respectively. The `TokenCredential` variants of the constructors are used because a default `TokenCredential` is set via the method call. + ## Configure multiple service clients with different names Imagine you have two storage accounts: one for private information and another for public information. Your app transfers data from the public to the private storage account after some operation. You need to have two storage service clients. To differentiate those two clients, use the extension method: From 80e3224cc3f00ccc11fcc5144718f99defdc6b0f Mon Sep 17 00:00:00 2001 From: Scott Addie Date: Tue, 25 Jul 2023 16:52:19 -0500 Subject: [PATCH 19/19] Simplify Program.cs --- .../dependency-injection/WebApplicationBuilder/Program.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs index 9d839b0f5a3dc..e659fb734a3b3 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -11,9 +11,6 @@ clientBuilder.UseCredential(new DefaultAzureCredential()); }); -builder.Services.AddEndpointsApiExplorer(); -builder.Services.AddSwaggerGen(); - WebApplication app = builder.Build(); #endregion snippet_WebApplicationBuilder