Decode.Storage.AzureBlob
3.0.0
dotnet add package Decode.Storage.AzureBlob --version 3.0.0
NuGet\Install-Package Decode.Storage.AzureBlob -Version 3.0.0
<PackageReference Include="Decode.Storage.AzureBlob" Version="3.0.0" />
<PackageVersion Include="Decode.Storage.AzureBlob" Version="3.0.0" />
<PackageReference Include="Decode.Storage.AzureBlob" />
paket add Decode.Storage.AzureBlob --version 3.0.0
#r "nuget: Decode.Storage.AzureBlob, 3.0.0"
#:package Decode.Storage.AzureBlob@3.0.0
#addin nuget:?package=Decode.Storage.AzureBlob&version=3.0.0
#tool nuget:?package=Decode.Storage.AzureBlob&version=3.0.0
Decode.Storage.AzureBlob
Azure Blob Storage implementation of IStorageService for the Decode.Storage ecosystem.
📦 Installation
dotnet add package Decode.Storage.AzureBlob
🛠️ Usage
1. Register Services
In your Program.cs or Startup.cs:
using Decode.Storage.AzureBlob.Extensions;
builder.Services.AddAzureBlobStorage(options =>
{
options.ConnectionString = "UseDevelopmentStorage=true"; // Azure Storage Account connection string
options.ContainerName = "my-container"; // Target container
options.CreateContainerIfNotExists = true; // Automatically create container on uploads if missing
});
This registration adds both IStorageService and IFileValidator (implemented by
FileSignatureValidator) as singletons. IStorageService is a singleton because its constructor
builds a BlobServiceClient, which is thread-safe and owns an HTTP connection pool that Microsoft
recommends creating once and reusing; it was transient before 2.0.0.
2. Inject and Use in Services
using Decode.Storage.Abstractions;
public class ProfileService
{
private readonly IStorageService _storage;
public ProfileService(IStorageService storage)
{
_storage = storage;
}
public async Task SaveAvatarAsync(Guid userId, Stream content)
{
// Uploads the stream directly to Azure Blob container, setting the appropriate Content-Type header.
string blobUrl = await _storage.UploadAsync($"avatars/{userId}.png", content, "image/png");
}
public async Task<StorageFile?> GetAvatarAsync(Guid userId)
{
// Downloads the file as a non-buffering stream directly from Azure Blob Storage.
return await _storage.DownloadAsync($"avatars/{userId}.png");
}
public async Task<string> GetTemporaryDownloadUrlAsync(Guid userId)
{
// Generates a secure pre-signed SAS URI that expires in 15 minutes.
// Requires an account key in the connection string — see below.
return await _storage.GetUrlAsync($"avatars/{userId}.png", DateTimeOffset.UtcNow.AddMinutes(15));
}
}
SAS generation requires a shared key
GetUrlAsync only signs a URI when expiration is supplied. Signing needs the account key, so the
client must have been built from a connection string that carries one. If the account is authenticated
any other way — Managed Identity, DefaultAzureCredential, a SAS-only connection string — the Azure
SDK cannot sign locally and the call throws:
InvalidOperationException: The BlobClient cannot generate a SAS URI.
Check account keys or authentication configurations.
This is the most common production surprise, because UseDevelopmentStorage=true and full
connection strings both work in development while Managed Identity is the usual choice once deployed.
With a credential-based client, issue a user delegation SAS through
BlobServiceClient.GetUserDelegationKeyAsync directly instead.
Calling GetUrlAsync without expiration returns the plain blob URI and never throws — but that URI
only resolves for callers who can authenticate, so it is not a substitute for a signed link on a
private container.
📄 License
MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Azure.Storage.Blobs (>= 12.27.0)
- Decode.Storage.Abstractions (>= 3.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
-
net8.0
- Azure.Storage.Blobs (>= 12.27.0)
- Decode.Storage.Abstractions (>= 3.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
-
net9.0
- Azure.Storage.Blobs (>= 12.27.0)
- Decode.Storage.Abstractions (>= 3.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 8.0.2)
- Microsoft.Extensions.Options (>= 8.0.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.