Middleware in .NET Core

Middleware in .NET Core

In the world of web development, middleware plays a crucial role in handling requests and responses. In the realm of .NET Core, middleware adds an extra layer of flexibility and control to your API projects. Whether you’re a seasoned developer or just starting with .NET Core, understanding how to work with both standard and custom middleware, and the order in which they execute can greatly enhance your API development skills. In this post, we will delve into the concept of middleware, walk you through real-time examples, and explore their features and advantages.

Middleware is a powerful feature of .NET Core that allows developers to add functionality to their applications without modifying the core code. Middleware is executed in a pipeline, and each middleware component can perform some processing on the request or response before passing it to the next middleware component in the pipeline.

What is Middleware?

Middleware, in the context of .NET Core, refers to components that are used to process requests and responses. They sit between the client and the server, intercepting and processing incoming requests before they reach the endpoint and likewise handling the response before it’s sent back. Middleware provides a way to add cross-cutting concerns like logging, authentication, caching, and more to your application’s processing pipeline.

There are two types of middleware in .NET Core: standard middleware and custom middleware. Standard middleware is provided by the .NET Core framework, and it includes middleware for tasks such as authentication, authorization, logging, and caching. Custom middleware is middleware that you create yourself, and it can be used to implement any functionality that you need.

Standard Middleware in .NET Core

.NET Core offers a range of built-in middleware that covers common scenarios. Some of these include:

  1. Authentication Middleware: This middleware helps authenticate users before they access specific resources within your API. It’s essential for ensuring that only authorized users can access sensitive parts of your application.
  2. Caching Middleware: Caching can significantly improve the performance of your application by storing frequently accessed data in memory. This middleware handles caching efficiently, reducing the load on your backend systems.
  3. Routing Middleware: Routing middleware is responsible for directing incoming requests to the appropriate controller and action methods based on the URL structure.

public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();

// Other middleware...
}

The **UseAuthentication**() the method tells the .NET Core framework to use **AuthenticationMiddleware** in the request pipeline. When a user makes a request to the application, the **AuthenticationMiddleware** will authenticate the user and then pass the request to the next middleware component in the pipeline.

If the user is not authenticated, the **AuthenticationMiddleware** will return a 401 Unauthorized response.

Custom Middleware in .NET Core

While the standard middleware provided by .NET Core is powerful, there are times when you need to tailor the middleware to fit your application’s specific needs. Custom middleware allows you to inject your own logic into the processing pipeline. This could include tasks like custom logging, header manipulation, request transformation, and more.

Real-Time Examples:

1. Custom Logging Middleware:

Let’s explore a real-world scenario where custom middleware shines: logging. Imagine you want to log incoming requests along with their relevant information such as the request method, URL, and timestamp. Here’s how you can create custom logging middleware:

Creating the custom middleware without inheriting from the IMiddleware interface.

public class LoggingMiddleware
{
private readonly RequestDelegate _next;

public LoggingMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context)
{
// Log the request information
string requestInfo = $"{DateTime.Now} - {context.Request.Method} {context.Request.Path}";
Console.WriteLine(requestInfo);

// Call the next middleware in the pipeline
await _next(context);
}
}

In this example, the **LoggingMiddleware** class captures the request information, logs it, and then passes the request to the next middleware in the pipeline.

Adding Custom Middleware to the Pipeline

To add your custom middleware to the pipeline, open the Startup.cs file of your .NET Core project and locate the **Configure** method. Here's how you can add the custom logging middleware:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Other middleware configurations

app.UseMiddleware();

// Other middleware configurations
}

2. Measure the Execution Time of Requests:

The next custom middleware is **RequestTimeMiddleware** to measure the execution time of requests.

The **RequestTimeMiddleware** is a very simple middleware. It simply measures the time it takes to process a request and then adds the execution time to the response headers.

Creating the custom middleware that inherits from the IMiddleware interface.

public class RequestTimeMiddleware : IMiddleware
{
public async Task InvokeAsync(HttpContext context, RequestDelegate next)
{
long startTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();

await next.Invoke(context);

long endTime = DateTimeOffset.Now.ToUnixTimeMilliseconds();

context.Response.Headers.Add("RequestTime", endTime - startTime);
}
}

The **InvokeAsync**() method first measures the start time of the request. Then, it calls the next delegate, which is the next middleware component in the pipeline. Finally, the **InvokeAsync**() method measures the end time of the request and adds the execution time to the response headers.

To use the **RequestTimeMiddleware**, I added it to the request pipeline in my Startup.cs file after the AuthenticationMiddleware.

public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseRequestTimeMiddleware();

// Other middleware...
}

Order of Middleware Execution

The order in which middleware components are added to the pipeline matters. They execute in the order they are added, and each middleware can choose to short-circuit the pipeline if necessary.

For instance, if authentication middleware is placed before routing middleware, unauthorized users won’t even reach the routing stage. Here’s the general order of execution:

  1. The request enters the pipeline.
  2. Middleware components execute in the order they are added.
  3. The request reaches the endpoint (controller action).
  4. Response travels back up the pipeline in reverse order.

Below is the order for both standard and custom middleware in.net core framework.

Advantages of Middleware

  1. Reusability: Middleware components can be reused across different parts of your application, promoting code consistency and reducing duplication.
  2. Modularity: Each middleware addresses a specific concern, making your codebase more organized and maintainable.
  3. Customizability: Custom middleware allows you to tailor the processing pipeline to your application’s unique requirements.
  4. Separation of Concerns: Middleware enables a clear separation between business logic and cross-cutting concerns, leading to cleaner and more focused code.
  5. Flexibility: You can combine various middleware components to achieve intricate processing flows, adapting to complex scenarios.

Middleware in .NET Core offers a powerful way to manage cross-cutting concerns and enhance the functionality of your API projects. By understanding the role of both standard and custom middleware, their execution order, and their advantages, you can take your .NET Core development skills to the next level.

Incorporating middleware effectively not only improves the performance and security of your applications but also makes your code more modular and maintainable. So, whether you’re building a small API or a complex web application, harness the potential of middleware to elevate your development game.

Thank you for reading until the end. Please consider following the writer and this publication. Visit Stackademic to find out more about how we are democratizing free programming education around the world.

Did you find this article valuable?

Support Dileep Sreepathi by becoming a sponsor. Any amount is appreciated!