Trigger Background Jobs from ASP.NET Core Middleware

October 20, 2025 · 7 min

ASP.NET Core middleware is a powerful component of the request pipeline, designed to handle HTTP requests and responses efficiently. But what happens when a request needs to kick off a task that shouldn’t block the response? Think of tasks like sending a confirmation email, generating a detailed audit log, or calling a slow third-party service. Running these directly within the middleware can severely impact your application’s performance and responsiveness.

The solution is to decouple these long-running operations from the request pipeline by offloading them to a background service. In this post, we’ll walk through the robust and recommended way to trigger background jobs from your middleware using IHostedService and an in-memory queue.

The Problem: Blocking the Pipeline

The request pipeline in ASP.NET Core is synchronous at its core, even with async/await. Each middleware component must complete its work before passing control to the next one. If your middleware performs a long-running operation, the client is left waiting until that task finishes.

For example, imagine a piece of middleware that logs detailed request information to a slow, remote data store:

// DO NOT DO THIS
app.Use(async (context, next) =>
{
    // This blocks the pipeline until the log is written
    await LogRequestDetailsToSlowStoreAsync(context.Request); 

    await next(context);
});

This approach creates a bottleneck. As traffic increases, requests will pile up waiting for these …

...

Read more

Dynamic Connection Strings for Multi-Tenant ASP.NET Apps

October 16, 2025 · 6 min

Building a multi-tenant SaaS application presents unique challenges, especially when it comes to data isolation. One of the most common and robust approaches is the “database-per-tenant” model, where each customer’s data resides in its own dedicated database. This ensures strong security and simplifies scaling.

The core problem, however, is telling your application which database to connect to for any given HTTP request. A static connection string in appsettings.json won’t work. We need a dynamic, request-aware mechanism. This is where ASP.NET Core middleware shines. By intercepting requests early, we can identify the tenant, retrieve their specific connection string, and configure services for the remainder of the request pipeline.

In this post, we’ll walk through building a middleware-based solution to manage tenant-aware connection strings in an ASP.NET Core application.

The Challenge with Static Configuration

In a typical single-tenant application, you register your DbContext like this:

// Program.cs - The traditional way
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));

This works because the connection string is known at startup and never changes. In a multi-tenant world, the connection string depends on who is making the request, a detail that is only available once the HTTP …

...

Read more

API Versioning in ASP.NET Core with Custom Middleware

October 15, 2025 · 7 min

As APIs evolve, the need to introduce breaking changes becomes inevitable. The key challenge is to roll out these updates without disrupting existing clients who depend on the current contract. This is where API versioning comes in. While feature-rich libraries like Asp.Versioning.Http are excellent, understanding how to build your own versioning scheme with middleware gives you maximum control and a deeper appreciation for the ASP.NET Core pipeline.

In this post, we’ll explore a clean, middleware-based approach to API versioning using a custom request header. We’ll build a solution that inspects a header and transparently rewrites the request path to route to the correct endpoint implementation.

Why a Middleware Approach?

Dedicated versioning libraries are powerful, offering features like API explorer integration, version advertisement, and conventions. However, a custom middleware solution offers its own set of advantages:

  • Full Control: You define the exact logic for how a version is resolved. You can read it from a header, a claim, a query string, or even a combination of factors.
  • Lightweight: You add only the logic you need, without any extra overhead.
  • Decoupled: The versioning logic lives in one place (the middleware) rather than being scattered across controllers with attributes. This can lead to cleaner endpoint definitions.
  • Great for Learning: Building it yourself is a fantastic way to understand how the ASP.NET Core request pipeline and routing work …
...

Read more

Dynamic Feature Toggles in ASP.NET Core Middleware

October 13, 2025 · 6 min

Deploying new features can be stressful. What if a bug slips through? What if you want to release a feature only to internal testers first? The traditional “deploy to release” model couples your deployment schedule directly with your feature launch, creating a high-stakes event. Feature flags, also known as feature toggles, offer a better way.

Feature flags allow you to decouple deployment from release. You can deploy new, unfinished, or experimental features to production but keep them “turned off.” This lets you enable them on-the-fly for specific users or a percentage of your user base, or quickly disable a feature that’s causing problems—all without a single redeployment.

In this post, we’ll explore how to implement feature flags in an ASP.NET Core application using the Microsoft.FeatureManagement library and custom middleware to control access to entire endpoints dynamically.

What Are Feature Flags?

At its core, a feature flag is a decision point in your code that can be toggled via configuration. Think of it as a dynamic if statement that you can control from outside your application’s code.

The benefits are significant:

  • Test in Production Safely: Deploy features to production and enable them only for your QA team.
  • Canary Releases & A/B Testing: Gradually roll out a new feature to a small percentage of users to monitor its performance and impact.
  • Kill Switch: Instantly disable a faulty feature in production if it’s …
...

Read more

Stream Responses in ASP.NET Core with Middleware

October 11, 2025 · 6 min

When building APIs that handle large datasets, memory consumption can quickly become a critical bottleneck. The default behavior in ASP.NET Core is to buffer the entire response in memory before sending it to the client. For a small JSON object, this is fine. For a 500 MB CSV export, it’s a recipe for disaster, potentially leading to high memory usage and even OutOfMemoryException.

The solution is response streaming. Instead of building the entire payload at once, we write it to the client in chunks as it’s generated. This drastically reduces the server’s memory footprint and improves the time to first byte (TTFB), making your application feel more responsive.

In this post, we’ll explore how to build a clean, reusable pattern for enabling response streaming using custom ASP.NET Core middleware.


The Problem with Response Buffering

Let’s visualize the default behavior. Imagine an endpoint that generates a large report:

  1. A request comes in for /api/reports/annual-sales.
  2. Your application logic queries a database and processes a massive amount of data.
  3. It serializes this data into a single, large string or byte array in memory. Let’s say it’s 200 MB.
  4. Only after the entire 200 MB payload is ready does ASP.NET Core begin sending the response to the client.

If 10 users request this report simultaneously, your server’s memory usage spikes by 2 GB just for these responses. This doesn’t scale well. Streaming sends the data piece by …

...

Read more

Inject Request Data into Services via ASP.NET Core Middleware

October 10, 2025 · 6 min

A common challenge in building complex ASP.NET Core applications, especially multi-tenant systems, is accessing request-specific data from deep within your service layer. How does a data repository or a business logic service know the current user’s ID, their permissions, or the tenant they belong to?

A naive approach is “prop-drilling”: passing the HttpContext or specific data points down through every method call. This clutters your method signatures and creates a maintenance nightmare. A slightly better approach might involve injecting IHttpContextAccessor, but this tightly couples your services to the HTTP infrastructure, making them difficult to test.

There is a cleaner, more powerful pattern: using middleware to populate a scoped service. This approach decouples your application logic from the web layer, improves testability, and keeps your code clean.


The Core Concept: Scoped Services as Request State

Dependency Injection in ASP.NET Core has three main lifetimes:

  • Singleton: One instance for the entire application lifetime.
  • Transient: A new instance is created every time it’s requested.
  • Scoped: A single instance is created for each client request (scope).

The scoped lifetime is the key to our solution. We can create a service, register it as scoped, and treat it as a container for all the data relevant to the current HTTP request. A middleware component, which runs at the start of the request, will be responsible for populating this container. …

...

Read more

ASP.NET Middleware Order Pitfalls That Break APIs

October 6, 2025 · 7 min

In ASP.NET Core, middleware components are the building blocks of your application’s request pipeline. Think of them as a series of checkpoints on an assembly line. Each request passes through these checkpoints in a specific order, and each one has a chance to inspect, modify, or even short-circuit the request.

While this architecture is incredibly powerful, it has a critical dependency: order matters. A lot. Arranging your middleware in the wrong sequence can lead to security vulnerabilities, broken functionality, and hours of frustrating debugging. Let’s dive into the most common ordering pitfalls that can silently break your APIs and how to fix them.

The Request Pipeline: A Two-Way Street

Before we get to the pitfalls, it’s essential to understand how the pipeline works. When an HTTP request arrives, it travels “down” the pipeline, passing through each middleware component in the order they were registered in Program.cs.

Once the request hits the end (usually your API endpoint), the response is generated and travels back “up” the pipeline in the reverse order. This two-way flow is why some middleware can act on both the incoming request and the outgoing response.

The golden rule is simple: Middleware registered earlier runs earlier on the request and later on the response.

Common Middleware Ordering Pitfalls

Let’s look at some classic mistakes. We’ll use the modern minimal API style with top-level statements for our …

...

Read more

Per-Request Tenant Resolution in ASP.NET Core Middleware

October 5, 2025 · 6 min

Building multi-tenant applications, a common pattern for Software as a Service (SaaS) products, introduces a fundamental challenge: how do you know which tenant is making the current request? Every incoming call to your API or web app must be correctly associated with a specific tenant to ensure data isolation and deliver a customized experience. The answer lies in a clean, powerful pattern: per-request tenant resolution using custom middleware.

In this guide, we’ll walk through creating a robust tenant resolution strategy in ASP.NET Core. We’ll build custom middleware that identifies the tenant from the incoming request and makes that information available to the rest of the application through dependency injection.


The Goal: What is Tenant Resolution?

At its core, tenant resolution is the process of inspecting an incoming HttpContext to extract a unique tenant identifier. Once you have this identifier, you can use it to look up the tenant’s details (like their database connection string, theme information, or feature flags) and load them into a request-scoped context.

There are several common strategies for identifying a tenant:

  • Hostname/Subdomain: tenant1.yourapp.com, tenant2.yourapp.com
  • URL Path: yourapp.com/tenants/tenant1/
  • HTTP Header: X-Tenant-Id: tenant1
  • Query String: yourapp.com/products?tenantId=tenant1

The beauty of the middleware approach is that it centralizes this logic, making your application cleaner and easier to maintain, regardless of …

...

Read more

ASP.NET Core Centralized Security Headers Middleware Guide

October 4, 2025 · 6 min

In modern web development, security isn’t an afterthought; it’s a foundational requirement. One of the most effective and straightforward ways to harden your ASP.NET Core application is by using HTTP security headers. These headers instruct the browser on how to behave, mitigating common attacks like Cross-Site Scripting (XSS), clickjacking, and protocol downgrade attacks.

While you can add these headers in various places, the most robust and maintainable approach is to create a single, centralized middleware. This ensures every response from your application is consistently protected.

In this post, we’ll build a configurable security headers middleware from scratch that manages Content-Security-Policy (CSP), HTTP Strict-Transport-Security (HSTS), and other essential headers.


Why a Centralized Middleware?

You might be tempted to sprinkle Response.Headers.Add(...) in your controllers or use separate app.Use...() calls for each header in Program.cs. However, a centralized approach offers significant advantages:

  • Consistency: Every single endpoint gets the same baseline protection without fail. You eliminate the risk of forgetting to secure a new API or page.
  • Single Point of Configuration: All your security header policies live in one place. Need to tighten your CSP? You only have one file to edit.
  • Maintainability: As security standards evolve, updating your policies is trivial. You don’t have to hunt down configurations scattered across the project. …
...

Read more

Writing a Minimal Custom Middleware in ASP.NET Core

October 1, 2025 · 5 min

ASP.NET Core’s request pipeline is a powerful concept built entirely around middleware. Think of it as an assembly line for your HTTP requests. Each station on the line is a piece of middleware that can inspect, modify, or act upon the request before passing it to the next station.

While ASP.NET Core provides a rich set of built-in middleware for things like routing, authentication, and static files, there will inevitably come a time when you need to create your own. Whether it’s for custom logging, header manipulation, or a unique authentication scheme, writing custom middleware is a fundamental skill.

In this guide, we’ll break down the process into its simplest form, showing you two minimal ways to create and use your own middleware.


Approach 1: The Convention-Based Class

The most common and structured way to create middleware is by defining a class that follows a specific convention. This approach is clean, reusable, and testable.

A middleware class needs two things:

  1. A constructor that accepts a RequestDelegate parameter. This delegate represents the next piece of middleware in the pipeline.
  2. A public method named InvokeAsync (or Invoke) that accepts an HttpContext as its first parameter. This is the method that gets executed.

Let’s create a simple middleware that logs the incoming request path and the outgoing response status code.

Step 1: Create the Middleware Class

Create a new file named SimpleLoggingMiddleware.cs. We’ll use a primary …

...

Read more