I am using net8 Azure Functions with Isolated model.
In the docs the sample shows using AddBlobServiceClient() to register an IAzureClientFactory<BlobServiceClient> which can then be injected into the function.
I would like to register two BlobContainerClient's each with its own container. My attempt is:
services.AddSingleton<BlobContainerClient>(provider =>
{
var configuration = provider.GetRequiredService<IConfiguration>();
var storageContainerName = configuration.GetValue<string>("AzureWebJobsStorage");
var blobServiceClient = provider.GetRequiredService<IAzureClientFactory<BlobServiceClient>>()
.CreateClient("inbound");
var blobContainerClient = blobServiceClient.GetBlobContainerClient(storageContainerName);
return blobContainerClient;
});
The problem with this is I now have a hard dependency upon BlobContainerClient which is difficult to test.
One extension method on AddBlobServiceClient is WithName() but I fail to see what use this is as I cannot see how to configure a BlobContainerClient as part of the registration of the BlobServiceClient.
In summary, my question is: How can I configure two individual BlobContainerClient's using the AddBlobServiceClient method in Program.cs and then inject one of two possibilities into a function?
It took quite some digging but here's how I achieved what I wanted and it remains testable which is awesome. It means I can configure my container names during registration and just inject them using an appropriate name.
...
builder.AddBlobServiceClient(Environment.GetEnvironmentVariable("AzureWebJobsStorage"))
.WithName("in1");
builder.AddClient<BlobContainerClient, BlobClientOptions>((options, provider) =>
{
var configuration = provider.GetRequiredService<IConfiguration>();
var storageContainerName = configuration.GetValue<string>("AzureWebJobsStorage");
var blobServiceClient = provider.GetRequiredService<IAzureClientFactory<BlobServiceClient>>()
.CreateClient("in1");
var blobContainerClient = blobServiceClient.GetBlobContainerClient("inbound");
return blobContainerClient;
})
.WithName("in2");
builder.AddClient<BlobClient, BlobClientOptions>((opts, provider) =>
{
var blobContainerClient = provider.GetRequiredService<IAzureClientFactory<BlobContainerClient>>().CreateClient("in2");
var blobClient = blobContainerClient.GetBlobClient("hello");
return blobClient;
})
.WithName("in3");
builder.AddClient<BlobContainerClient, BlobClientOptions>((options, provider) =>
{
var configuration = provider.GetRequiredService<IConfiguration>();
var storageContainerName = configuration.GetValue<string>("AzureWebJobsStorage");
var blobServiceClient = provider.GetRequiredService<IAzureClientFactory<BlobServiceClient>>()
.CreateClient("in1");
var blobContainerClient = blobServiceClient.GetBlobContainerClient("outbound");
return blobContainerClient;
})
.WithName("out1");
builder.AddClient<BlobClient, BlobClientOptions>((opts, provider) =>
{
var blobContainerClient = provider.GetRequiredService<IAzureClientFactory<BlobContainerClient>>().CreateClient("out1");
var blobClient = blobContainerClient.GetBlobClient("goodbye");
return blobClient;
})
.WithName("out2");
...
And then in your consuming class:
public Consumer(ILogger<NewClientHandoff> logger,
IAzureClientFactory<BlobServiceClient> blobClientFactory,
IAzureClientFactory<BlobContainerClient> c,
IAzureClientFactory<BlobClient> d)
{
_c = c.CreateClient("in1");
_d = d.CreateClient("out2");
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With