Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 9

Managing Blob Metadata with Azure SDK for .NET

Recommended resources

Hello! In our last lesson, you built a .NET console application to perform the fundamental lifecycle operations on blobs: uploading, listing, downloading, and deleting. This gave you programmatic control over the data within your Azure Storage containers.

Today, we'll build on that foundation by exploring how to manage data about your data. The learning outcome for this lesson is to set and retrieve blob metadata programmatically using the Azure SDK for .NET. Metadata allows you to store custom key-value pairs with your blobs, which is invaluable for categorizing, filtering, or processing files without needing to read their contents.

1. Understanding Blob Properties and Metadata

Before we write any code, it's important to understand what metadata is and how it differs from other properties associated with a blob. Azure blobs have two kinds of descriptive data: system properties and user-defined metadata.

Manage properties and metadata for a blob with .NET - Azure Storage

This section from the official Microsoft documentation clearly explains the difference between read-only system properties (like creation time) and the user-defined metadata that you can control.

Please read the section titled About properties and metadata. As you read, focus on: The definition of System properties and User-defined metadata. The naming requirements for metadata, specifically that they must adhere to HTTP header naming conventions. The important distinction between metadata and blob index tags. While similar, only index tags are automatically indexed and searchable by the Blob service itself. This is a common point of confusion and an important detail for the AZ-204 exam.

To summarize, system properties are managed by Azure (e.g., LastModified, ContentType), while metadata is entirely for your application's use. You can add, for example, a processed="false" flag, a document-type="invoice", or a customerId="12345" to a blob.

This metadata is visible directly in the Azure Portal, as shown in the image below.

Metadata associated with a blob, viewed in the Azure Portal. You can see a key named 'firstkey' with its corresponding value.

2. Setting and Retrieving Metadata in .NET

Now, let's look at the C# implementation. As you'll see, the process is straightforward and leverages the BlobClient you're already familiar with from the previous lesson.

Manage properties and metadata for a blob with .NET - Azure Storage

This part of the documentation provides the exact code examples you need to implement this lesson's learning outcome.

Read the section Set and retrieve metadata. Pay close attention to the two code examples: AddBlobMetadataAsync: This shows how to create a Dictionary<string, string> and use the SetMetadataAsync method to attach it to a blob. ReadBlobMetadataAsync: This demonstrates using GetPropertiesAsync to fetch the blob's properties and then iterating through the Metadata collection to read the key-value pairs.

To see this in action, the following short video provides a quick and practical demonstration of setting metadata and then verifying it in the Azure Portal.

Azure Blob Storage - Read and Write Within MINUTES!

This clip from a Dev Leader video concisely demonstrates the process of setting metadata programmatically and confirming the result.

Watch from setting metadata to see the C# code for creating a dictionary and applying it to a blob. Then, continue watching from verifying in the portal to see how the result appears in the Azure UI.

The key methods to remember are:

  • BlobClient.SetMetadataAsync(IDictionary<string, string> metadata): Overwrites any existing metadata on the blob with the new collection you provide.
  • BlobClient.GetPropertiesAsync(): Returns a BlobProperties object which contains both system properties and a Metadata dictionary.

3. Practical Exercise: Enhance Your Blob Manager

It's time to apply what you've learned. Let's update the console application from the previous lesson to include metadata operations.

Below is the code from last time. Your task is to modify it to:

  1. After uploading the blob, create a dictionary with at least two key-value pairs (e.g., docType and createdBy) and set it as the blob's metadata.
  2. After listing the blobs, add a new step to retrieve the properties of the blob you just uploaded.
  3. Print the retrieved metadata to the console to verify that your SetMetadataAsync call was successful.

Here's the starting code:

using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System.IO;
using System.Threading.Tasks;
using System;
using System.Collections.Generic; // Add this for the dictionary

class Program
{
    static async Task Main()
    {
        Console.WriteLine("Azure Blob Storage - .NET SDK Quickstart with Metadata\n");

        string connectionString = "PASTE_YOUR_CONNECTION_STRING_HERE";
        BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);

        string containerName = "documents";
        BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);

        Console.WriteLine($"Working with container: {containerName}");

        string localPath = "data";
        Directory.CreateDirectory(localPath);
        string fileName = "quickstart" + Guid.NewGuid().ToString() + ".txt";
        string localFilePath = Path.Combine(localPath, fileName);

        await File.WriteAllTextAsync(localFilePath, "Hello, from my .NET App!");

        BlobClient blobClient = containerClient.GetBlobClient(fileName);
        Console.WriteLine($"Uploading to Blob storage as blob:\n\t{blobClient.Uri}\n");
        await blobClient.UploadAsync(localFilePath, true);

        // --- TODO: ADD CODE HERE TO SET METADATA ---
        Console.WriteLine("Setting metadata...");
        // 1. Create a Dictionary<string, string>
        // 2. Call blobClient.SetMetadataAsync()
        
        Console.WriteLine("\nListing blobs in container...");
        await foreach (BlobItem blobItem in containerClient.GetBlobsAsync())
        {
            Console.WriteLine($"\t{blobItem.Name}");
        }
        Console.WriteLine();
        
        // --- TODO: ADD CODE HERE TO READ METADATA ---
        Console.WriteLine("Reading blob metadata...");
        // 1. Call blobClient.GetPropertiesAsync()
        // 2. Loop through the properties.Metadata collection and print each key/value pair
        
        string downloadFilePath = localFilePath.Replace(".txt", "DOWNLOADED.txt");
        Console.WriteLine($"\nDownloading blob to\n\t{downloadFilePath}\n");
        await blobClient.DownloadToAsync(downloadFilePath);
        
        Console.Write("Press any key to begin clean up...");
        Console.ReadLine();

        Console.WriteLine("Deleting blob...");
        await blobClient.DeleteAsync();
        
        Console.WriteLine("Deleting local files...");
        File.Delete(localFilePath);
        File.Delete(downloadFilePath);
        Console.WriteLine("Done.");
    }
}

Once you've tried it, compare your solution with the completed code below.

Click to see the complete solution
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Models;
using System.IO;
using System.Threading.Tasks;
using System;
using System.Collections.Generic;

class Program
{
    static async Task Main()
    {
        Console.WriteLine("Azure Blob Storage - .NET SDK Quickstart with Metadata\n");

        // --- 1. CONNECT TO AZURE STORAGE ---
        string connectionString = "PASTE_YOUR_CONNECTION_STRING_HERE";
        BlobServiceClient blobServiceClient = new BlobServiceClient(connectionString);

        // --- 2. GET CONTAINER CLIENT AND CREATE LOCAL FILE ---
        string containerName = "documents";
        BlobContainerClient containerClient = blobServiceClient.GetBlobContainerClient(containerName);

        Console.WriteLine($"Working with container: {containerName}");

        string localPath = "data";
        Directory.CreateDirectory(localPath);
        string fileName = "quickstart" + Guid.NewGuid().ToString() + ".txt";
        string localFilePath = Path.Combine(localPath, fileName);

        await File.WriteAllTextAsync(localFilePath, "Hello, from my .NET App!");

        // --- 3. UPLOAD THE BLOB ---
        BlobClient blobClient = containerClient.GetBlobClient(fileName);
        Console.WriteLine($"Uploading to Blob storage as blob:\n\t{blobClient.Uri}\n");
        await blobClient.UploadAsync(localFilePath, true);

        // --- 4. SET METADATA ---
        Console.WriteLine("Setting metadata...");
        IDictionary<string, string> metadata = new Dictionary<string, string>
        {
            { "docType", "textDocument" },
            { "createdBy", "DotNetApp" }
        };
        await blobClient.SetMetadataAsync(metadata);
        Console.WriteLine("Metadata set successfully.");

        // --- 5. LIST BLOBS ---
        Console.WriteLine("\nListing blobs in container...");
        await foreach (BlobItem blobItem in containerClient.GetBlobsAsync())
        {
            Console.WriteLine($"\t{blobItem.Name}");
        }
        Console.WriteLine();

        // --- 6. READ METADATA ---
        Console.WriteLine("Reading blob metadata...");
        BlobProperties properties = await blobClient.GetPropertiesAsync();
        foreach (var metadataItem in properties.Metadata)
        {
            Console.WriteLine($"\tKey: {metadataItem.Key}, Value: {metadataItem.Value}");
        }

        // --- 7. DOWNLOAD THE BLOB ---
        string downloadFilePath = localFilePath.Replace(".txt", "DOWNLOADED.txt");
        Console.WriteLine($"\nDownloading blob to\n\t{downloadFilePath}\n");
        await blobClient.DownloadToAsync(downloadFilePath);

        // --- 8. DELETE THE BLOB & CLEAN UP ---
        Console.Write("Press any key to begin clean up...");
        Console.ReadLine();

        Console.WriteLine("Deleting blob...");
        await blobClient.DeleteAsync();
        
        Console.WriteLine("Deleting local files...");
        File.Delete(localFilePath);
        File.Delete(downloadFilePath);
        Console.WriteLine("Done.");
    }
}

When you run the final code, you should see your custom metadata printed to the console, confirming that the entire round-trip operation was successful.


Conclusion

Congratulations! You have now extended your ability to manage blobs by adding custom metadata. This skill is essential for building sophisticated applications on Azure Storage.

Here are the key takeaways from today's lesson:

  • Blob metadata consists of user-defined key-value pairs stored with a blob.
  • In .NET, metadata is represented by an IDictionary<string, string>.
  • You use BlobClient.SetMetadataAsync() to write metadata and BlobClient.GetPropertiesAsync() to read it via the Metadata property of the returned BlobProperties object.

In the next lesson, we will tackle another important programmatic concept: implementing blob lease management to control concurrency. This will allow you to lock a blob to prevent other processes from modifying it while you are working with it.