Skip to content

Blob Storage Integration

Demonstrates file upload and blob storage management using Azure Blob Storage with Aspire's emulator for local development.

📋 Overview

This example shows how to:

  • Set up Azure Blob Storage integration with Aspire 13.1.0
  • Build a file upload API using .NET 10.0 minimal APIs
  • Create a React frontend with drag-and-drop file upload
  • Use the Azure Storage emulator for local development
  • Implement proper error handling and type safety

🏗️ Architecture

flowchart LR
    subgraph Frontend["React Frontend"]
        Upload["Upload Component<br/>(Drag & Drop)"]
    end
    subgraph API["Aspire Application"]
        AppHost["AppHost<br/>(Orchestration)"]
        BlobAPI["Blob API<br/>(.NET 10)<br/>(Minimal APIs)"]
        Emulator["Azure Storage<br/>Emulator"]
    end

    Upload -->|POST /api/upload<br/>GET /api/files| BlobAPI
    BlobAPI --> Emulator
    AppHost -.->|Manages| Emulator
    AppHost -.->|Hosts| BlobAPI

🧩 Components

Project Description
blobstorage.AppHost Aspire orchestration for API and emulator
blobstorage .NET 10 API with blob upload/list endpoints
blobstorage.Frontend React + Vite frontend with upload component

🔑 Key Features

  • File Upload API: POST endpoint to upload files to blob storage
  • Blob Listing: GET endpoint to retrieve stored files with metadata
  • Drag-and-Drop UI: React component with drag-and-drop file selection
  • Progress Tracking: Real-time upload progress feedback
  • Error Handling: Comprehensive error handling with JSON responses
  • Azure Storage Emulator: Local development without cloud costs
  • Aspire 13.1.0: Modern service orchestration and service defaults
  • .NET 10 LTS: Latest long-term support framework
  • Central Package Management: Centralized dependency versioning

📂 Project Structure

foundry/dotnet/aspire-blobstorage/
├── blobstorage.sln
├── Directory.Build.props              # .NET 10.0 configuration
├── Directory.Packages.props           # Central package management
├── README.md                          # Project documentation
├── blobstorage.AppHost/
│   ├── Program.cs                     # Aspire orchestration
│   └── blobstorage.AppHost.csproj
├── src/blobstorage/
│   ├── Program.cs                     # Blob API endpoints
│   └── blobstorage.csproj
└── src/blobstorage.Frontend/
    ├── src/
    │   ├── App.tsx                    # Main React component
    │   ├── pages/
    │   │   ├── Upload.tsx             # File upload page
    │   │   ├── Home.tsx               # Home page
    │   │   ├── User.tsx               # User info page
    │   │   ├── Login.tsx              # Login page
    │   │   └── Logout.tsx             # Logout page
    │   ├── components/
    │   │   └── Header/
    │   │       ├── Header.tsx         # Navigation header
    │   │       └── Header.css
    │   ├── navigation/
    │   │   ├── Routes.tsx             # Route definitions
    │   │   └── paths.ts               # Path constants
    │   ├── App.css                    # Application styles
    │   └── index.css                  # Global CSS
    ├── package.json
    ├── vite.config.ts                 # Vite configuration
    └── tsconfig.json

🚀 Getting Started

Prerequisites

  • .NET 10.0 SDK
  • Node.js 22.x or 24.x
  • Azure Storage Emulator (Azurite) or local installation

Running the Application

cd foundry/dotnet/aspire-blobstorage
dotnet run --project blobstorage.AppHost

The application will:

  1. Start the Azure Storage emulator (Azurite)
  2. Create a blob container for storage
  3. Start the .NET API server
  4. Serve the React frontend at the configured base path

API Endpoints

Method Endpoint Description
POST /api/upload Upload a file to blob storage
GET /api/files List all blobs with metadata
GET / Health check endpoint

API Response Examples

Upload Success (200):

{
  "status": "success",
  "message": "File uploaded successfully",
  "fileName": "example.txt",
  "blobUri": "https://..."
}

List Files (200):

{
  "files": [
    {
      "name": "example.txt",
      "size": 1024,
      "created": "2025-12-19T22:00:00Z",
      "url": "https://..."
    }
  ]
}

Error (500):

{
  "status": "error",
  "message": "Failed to upload file",
  "details": "The blob container does not exist"
}

🎨 Frontend Features

Upload Component

The Upload.tsx component provides:

  • Drag-and-Drop Zone: Drop files directly onto the upload area
  • File Input: Standard file selection dialog fallback
  • Progress Display: Real-time upload progress with percentage
  • File List: Display uploaded files with metadata
  • Error Handling: Graceful error messages for failed uploads
  • Environment Configuration: Dynamic backend URL via VITE_BACKEND_URL

Styling

Modern, responsive design with:

  • CSS Variables: Centralized design tokens (colors, spacing, typography)
  • Glassmorphism Effects: Frosted glass navigation and cards
  • Smooth Animations: Transitions and hover effects
  • Dark Mode Support: Light and dark theme compatibility
  • Responsive Grid: Mobile-first layout

🔒 Azure Blob Storage Configuration

Local Development (Azurite)

The application automatically configures Azure Storage Emulator for local development:

// AppHost.cs
var blobs = builder.AddAzureStorage("storage")
    .AddBlobs("blobs");

Azurite provides free local storage that matches the production Azure API.

Production Configuration

Update the Aspire configuration to use actual Azure Storage:

// Use managed identity or connection string
builder.AddAzureStorage("storage")
    .AddBlobs("blobs");

📚 Learn More

🛠️ Technologies

Technology Version Purpose
.NET Framework 10.0 Application framework
Aspire 13.1.0 Orchestration and defaults
Azure Storage Latest Blob storage service
React 19 Frontend UI framework
TypeScript 5.9+ Type-safe JavaScript
Vite Latest Frontend build tool
SAIF.Platform 3.0.3 Platform packages

✅ Quality Indicators

  • ✅ Full-stack example: API + React frontend
  • ✅ Real-world patterns: File upload, error handling, progress tracking
  • ✅ Local development: Azurite emulator included
  • ✅ Modern tooling: .NET 10, Aspire 13.1, React 19
  • ✅ Type safety: TypeScript throughout
  • ✅ Responsive design: Works on mobile and desktop
  • ✅ Production-ready code: Proper error handling and validation