C# and .NET examples · Azure Functions

Azure Functions Middleware: The .NET 6 Comparison

A side-by-side comparison of two Azure Functions v4 projects on .NET 6: one using isolated worker middleware (WithMiddleware, built on IFunctionsWorkerMiddleware) and one without middleware (WithoutMiddleware, an in-process function). Both expose a SendMessage HTTP POST endpoint that greets the caller by name, but the middleware version transforms the name to uppercase before the function handler runs.

In this guide: Get started · Walk through the example · Understand the details · Check the limits

✨ Features

Projects

Project Port Description
WithMiddleware 7052 Registers UppercaseNameMiddleware; name is uppercased in middleware before reaching the handler
WithoutMiddleware 7162 In-process model (Microsoft.NET.Sdk.Functions), no middleware; the raw name field from the JSON body is used as-is

This comparison also changes the hosting model: it is not a comparison of two otherwise identical apps with just one middleware registration removed. An isolated worker app can also run without custom middleware.

🚀 Quick start

Running Locally

From the repository root, use a separate terminal for each command group:

# With middleware
cd Middleware/Dotnet6/WithMiddleware
func start --port 7052

# Without middleware (separate terminal)
cd Middleware/Dotnet6/WithoutMiddleware
func start --port 7162

📦 Prerequisites and installation

Requirements

Minimum local.settings.json (WithMiddleware)

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
  }
}

For the in-process WithoutMiddleware project, set "FUNCTIONS_WORKER_RUNTIME": "dotnet" instead of "dotnet-isolated".

NuGet Packages (WithMiddleware)

Package Version
Microsoft.Azure.Functions.Worker 1.19.0
Microsoft.Azure.Functions.Worker.Extensions.Http 3.0.13
Microsoft.Azure.Functions.Worker.Sdk 1.14.0
Newtonsoft.Json 13.0.1

WithoutMiddleware references only Microsoft.NET.Sdk.Functions 4.2.0.

💡 Usage

How the Middleware Works

UppercaseNameMiddleware implements IFunctionsWorkerMiddleware:

  1. Reads the HTTP request body as a string
  2. Parses it as JSON (JObject)
  3. Converts the name property value to uppercase (or sets it to "name not found" if absent)
  4. Stores the updated JObject in context.Items["updated_body"]
  5. Resets the request body stream position
  6. Calls next(context) to pass control to the function handler

The SendMessageFunction then reads context.Items["updated_body"] and returns Hello {name}.

# With middleware — name is returned in uppercase
curl -X POST http://localhost:7052/api/SendMessage \
  -H "Content-Type: application/json" \
  -d '{"name": "alice"}'

Response: Hello ALICE.

# Missing name field
curl -X POST http://localhost:7052/api/SendMessage \
  -H "Content-Type: application/json" \
  -d '{}'

Response: Hello name not found.

# Without middleware — name is used as-is
curl -X POST http://localhost:7162/api/SendMessage \
  -H "Content-Type: application/json" \
  -d '{"name": "alice"}'

Response: Hello, alice. This HTTP triggered function executed successfully. (with no name, it asks you to pass one).

🏗️ Architecture

Project Structure

Dotnet6/
├── WithMiddleware/
│   ├── Functions/
│   │   └── SendMessageFunction.cs      # Reads updated_body from context.Items
│   ├── Middlewares/
│   │   └── UppercaseNameMiddleware.cs  # Transforms name to uppercase
│   ├── Program.cs                      # Registers middleware
│   └── WithMiddleware.csproj
├── WithoutMiddleware/
│   ├── Functions/
│   │   └── SendMessageFunction.cs      # Reads name directly from request body
│   └── WithoutMiddleware.csproj
└── readme.md

🧪 Development and testing

Build the two projects independently and compare the same valid-name request on ports 7052 and 7162. Also check missing names, malformed JSON and whether the selected host provides a seekable request stream. These checks were not executed against a running host in this review.

🛠️ Troubleshooting and limitations

Start Azurite for the development storage setting. The isolated middleware sets requestData.Body.Position = 0; a non-seekable body stream can fail at that line. It parses and logs the entire request body without an exception handler or sensitive-field redaction. The examples use Bash curl syntax; on PowerShell, use curl.exe with appropriate JSON quoting or Invoke-RestMethod.


Read all C# and .NET Code Examples guides online · Project overview · All developer projects