Middleware is a component that is assembled into the application pipeline to handle requests and responses.
Middlewares are chained one-after-other and execute in the same sequence how they're added.
Middleware can be a request delegate (anonymous method or lambda expression) [or] a class.
Middleware class is used to separate the middleware logic from a lambda expression to a separate / reusable class.
Middleware extension method is used to invoke the middleware with a single method call.
Example
Program.cs
using MyFirstApp.CustomMiddleware;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddTransient<MyCustomMiddleware>();//Add custom middleware using DI
var app = builder.Build();
//app.MapGet("/", () => "Hello World!");
//Request Response Modification
/*app.Run(async (HttpContext context) =>
{
context.Response.StatusCode = 400;
context.Response.Headers["MyKey"] = "my value";
await context.Response.WriteAsync("<h1>Hello</h1>");
await context.Response.WriteAsync("World");
}
);*/
//Middleware: Teminal or short circuit, it will not forward the request of the next middleware, so only render Hello
/*app.Run(async(HttpContext context) => {
await context.Response.WriteAsync("Hello");
});
app.Run(async (HttpContext context) => {
await context.Response.WriteAsync("Hello again");
});
*/
//Middleware Chain: O/p without queryString = From Middleware1 My custom middleware- starts From Middleware1 My custom middleware- ends. NOTE: data type HttpContext and RequestDelegate are optional
app.Use(async (HttpContext context, RequestDelegate next) => {
await context.Response.WriteAsync("From Middleware1 ");
await next(context);
});
//Middleware in custom class
//app.UseMiddleware<MyCustomMiddleware>();//without extension method, Option1
//app.UseMyCustomMiddleware();//Using extension method,Option2
//app.UseHelloCustomMiddleware();//use VS generated middleware class, Option3
//Middleware useWhen, O/p: From Middleware1 -Hello from Middleware Branch- From Middleware12
app.UseWhen(context=>context.Request.Query.ContainsKey("userName"),
app => {
app.Use(async (context, next) =>
{
await context.Response.WriteAsync("-Hello from Middleware Branch-");
await next(context);
});
});
app.Run(async (HttpContext context) => {
await context.Response.WriteAsync(" From Middleware12 ");
});
app.Run();
MyCustomMiddleware.cs
namespace MyFirstApp.CustomMiddleware
{
public class MyCustomMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
await context.Response.WriteAsync("My custom middleware- starts");
await next(context);
await context.Response.WriteAsync("My custom middleware- ends");
}
}
public static class CustomMiddlewareExtension
{
public static IApplicationBuilder UseMyCustomMiddleware(this IApplicationBuilder app) {
return app.UseMiddleware<MyCustomMiddleware>();
}
}
}
HelloCustomMiddleware.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using System.Linq;
using System.Threading.Tasks;
//generated automatically from add new item-?Middleware class
namespace MyFirstApp.CustomMiddleware
{
// You may need to install the Microsoft.AspNetCore.Http.Abstractions package into your project
public class HelloCustomMiddleware
{
private readonly RequestDelegate _next;
public HelloCustomMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext httpContext)
{
if(httpContext.Request.Query.ContainsKey("firstName")
&& httpContext.Request.Query.ContainsKey("lastName"))
{
string fullName = httpContext.Request.Query
["firstName"] + " " +
httpContext.Request.Query["lastName"];
await httpContext.Response.WriteAsync(fullName);
}
await _next(httpContext);
}
}
// Extension method used to add the middleware to the HTTP request pipeline.
public static class HelloCustomMiddlewareExtensions
{
public static IApplicationBuilder UseHelloCustomMiddleware(this IApplicationBuilder builder)
{
return builder.UseMiddleware<HelloCustomMiddleware>();
}
}
}