ASP.NET Core Middleware: Ultimate Guide - IndianTechnoEra
Latest update Android YouTube

ASP.NET Core Middleware: Ultimate Guide

Middleware is the backbone of the ASP.NET Core request pipeline. Understanding middleware deeply is essential for building robust, secure, and high-performance web applications — and it's one of the most asked topics in .NET interviews.


📌 What Exactly is Middleware?

Middleware is software that is assembled into an application pipeline to handle HTTP requests and responses. Each middleware component can:

  • ✅ Execute logic before the next middleware.
  • Pass the request to the next middleware (or short-circuit).
  • ✅ Execute logic after the next middleware (on the way back).
  • Short-circuit the pipeline to prevent further processing.

🔁 How the Pipeline Works

  • Request flows from left (first middleware) to right (last middleware).
  • Response flows back from right to left.
  • Each middleware can decide whether to call the next middleware using next() or return early.

🧩 Types of Middleware (Interview Ready)

  • Built-in Middleware – Provided by ASP.NET Core.
    Example: UseAuthentication, UseAuthorization, UseStaticFiles, UseExceptionHandler, UseRouting.
  • Custom Middleware – Developer-created for specific cross-cutting concerns.
    Use cases: Logging, request/response modification, tenant resolution, IP whitelisting, custom headers.
  • Third-party Middleware – From external NuGet packages.
    Examples: Serilog (logging), Swagger (API docs), Health Checks, Rate limiting.
  • Terminal Middleware – The last middleware that produces a response and doesn't call next.
    Examples: Run(), MVC endpoints, static files when found.

🛠️ Use, Map, and Run Methods – Explained

  • Use() – Adds middleware that can call the next delegate. Most common.
  • Run() – Adds terminal middleware (no next parameter).
  • Map() / MapWhen() – Branches the pipeline based on request path or condition.

Code Example – All Three

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

// Use - can call next
app.Use(async (context, next) => {
    Console.WriteLine("Before next");
    await next();
    Console.WriteLine("After next");
});

// Map - branch for specific path
app.Map("/admin", adminApp => {
    adminApp.Run(async context => {
        await context.Response.WriteAsync("Admin area");
    });
});

// Run - terminal middleware
app.Run(async context => {
    await context.Response.WriteAsync("Hello from terminal");
});

📋 Common Built-in Middlewares (Purpose & Order)

MiddlewarePurposeWhen to place
UseExceptionHandlerGlobal exception handling & fallbackFirst (early capture)
UseHstsEnforce HTTPS Strict Transport SecurityEarly (security)
UseHttpsRedirectionRedirect HTTP → HTTPSEarly
UseStaticFilesServe static files (CSS, JS, images)Before auth (performance)
UseRoutingMatch request to endpointAfter static files, before auth
UseAuthenticationIdentify userAfter routing, before authz
UseAuthorizationCheck permissionsAfter authentication
UseResponseCachingCache responsesBefore auth if public cache
UseCorsCross-Origin Resource SharingBefore auth & routing
MapControllers / EndpointsExecute MVC/API actionsLast

⚠️ Why Order Matters – Critical for Interviews

✅ Correct Order (Recommended)
ExceptionHandler → HSTS → HTTPS Redirection → StaticFiles → Routing → CORS → Authentication → Authorization → Endpoints

❌ Incorrect Order (Problems you will face)
- UseStaticFiles after UseAuthorization → Secure files might be blocked incorrectly.
- UseExceptionHandler at the end → Exceptions won't be caught.
- UseAuthentication after UseAuthorization → User not identified when authorizing (throws).
- UseRouting after UseAuthentication → Authentication might not have route data.

🎯 Interview Question: "What happens if I put UseAuthentication after UseAuthorization?"

Answer: The authorization middleware will execute before authentication, meaning the user identity will not be established. This typically throws an InvalidOperationException because authorization depends on authentication results. Always place UseAuthentication before UseAuthorization.


📦 Real Example: Complete Program.cs (Modern .NET 8/9)

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();           // Serve wwwroot files
app.UseRouting();
app.UseCors("AllowSpecific");   // After routing, before auth
app.UseAuthentication();        // Who are you?
app.UseAuthorization();         // Are you allowed?
app.MapControllers();           // Terminal middleware

app.Run();

🛡️ Creating Custom Middleware – Step by Step

Custom middleware is great for logging, request validation, tenant detection, etc.

Approach 1: Inline Middleware (for simple cases)

app.Use(async (context, next) => {
    Console.WriteLine($"Request: {context.Request.Method} {context.Request.Path}");
    await next();
    Console.WriteLine($"Response: {context.Response.StatusCode}");
});

Approach 2: Dedicated Middleware Class (recommended)

public class RequestLoggingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;

    public RequestLoggingMiddleware(RequestDelegate next, ILogger<RequestLoggingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        _logger.LogInformation("Handling request: {Path}", context.Request.Path);
        await _next(context); // Call next middleware
        _logger.LogInformation("Finished request with status: {StatusCode}", context.Response.StatusCode);
    }
}

// Register in Program.cs
app.UseMiddleware<RequestLoggingMiddleware>();

🔥 Short-circuiting Example (IP Blocking)

app.Use(async (context, next) => {
    var blockedIp = "192.168.1.100";
    if (context.Connection.RemoteIpAddress?.ToString() == blockedIp)
    {
        context.Response.StatusCode = 403;
        await context.Response.WriteAsync("Forbidden");
        return; // short-circuit – does NOT call next()
    }
    await next();
});

🧠 Interview Questions & Answers (Must Know)

Q1: What is the difference between Use() and Run()?

A: Use() expects a next delegate and can pass control to the next middleware. Run() does not have a next parameter and terminates the pipeline (terminal middleware).

Q2: How do you conditionally branch the pipeline?

A: Using Map() (based on path) or MapWhen() (based on predicate). Example: app.Map("/api", apiApp => { ... });

Q3: Can middleware run after the response has started?

A: Once the response has started (headers sent), modifying response body may throw. Always check context.Response.HasStarted before writing.

Q4: How to handle exceptions globally?

A: Use UseExceptionHandler as the first middleware. It catches exceptions from subsequent middleware and can re-execute the pipeline on an error route.

Q5: What is the difference between app.UseAuthorization() and adding [Authorize] attributes?

A: UseAuthorization adds the authorization middleware to the pipeline. [Authorize] attributes are policy/requirements evaluated by that middleware. Both are required – middleware enables the feature, attributes define rules.


✅ Best Practices (For Production & Interviews)

  • Order matters – exceptions first, security early, endpoints last.
  • Single responsibility – each middleware does one thing.
  • Don't block async – always use await next() and async signatures.
  • Handle exceptions earlyUseExceptionHandler should be first.
  • Use built-in middleware instead of reinventing (CORS, caching, static files).
  • Document custom middleware order in large teams.
  • Be careful with short-circuiting – ensure you don't accidentally skip required middleware (e.g., auth).

🎯 Final Key Takeaway

Middleware is the heart of ASP.NET Core request processing. Mastering Use, Map, Run and the correct middleware order is critical for building secure, maintainable, and high-performance applications. In interviews, expect scenario-based questions like "Arrange these middlewares in correct order" or "Write a custom logging middleware".

✅ Bookmark this guide for your next .NET interview or real-world project!

إرسال تعليق

Feel free to ask your query...
Cookie Consent
We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience.
Oops!
It seems there is something wrong with your internet connection. Please connect to the internet and start browsing again.
AdBlock Detected!
We have detected that you are using adblocking plugin in your browser.
The revenue we earn by the advertisements is used to manage this website, we request you to whitelist our website in your adblocking plugin.
Site is Blocked
Sorry! This site is not available in your country.