By Andrew Lock

The word middleware is used in a variety of contexts in software development and IT, but it’s not a particularly descriptive word – so, what is middleware? This article discusses the definition of middleware in ASP.NET Core and how they can be used.

Save 37% off ASP.NET Core in Action with code lockaspdotnet.

In ASP.NET Core, middleware are C# classes that can handle an HTTP request or response. Middleware can either:

  • Handle an incoming HTTP request by generating an HTTP response.

  • Process an incoming HTTP request, modify it, and pass it on to another piece of middleware.

  • Process an outgoing HTTP response, modify it, and pass it on to either another piece of middleware, or the ASP.NET Core web server.

For example, a piece of logging middleware might note down when a request arrived and then pass it on to another middleware. Meanwhile, an image resizing middleware component might spot an incoming request for an image with a specified size, generate the requested image, and send it back to the user without passing it on.

The most important piece of middleware in most ASP.NET Core applications is the MvcMiddleware. This normally generates your HTML pages and API responses. Like the image resizing middleware, it typically receives a request, generates a response, and then sends it back to the user, as shown in figure 1.


Figure 1 Example of a middleware pipeline. Each middleware handles the request and passes it on to the next middleware in the pipeline. After a middleware generates a response, it passes it back through the pipeline. When it reaches the ASP.NET Core web server, the response is sent to the user’s browser.


This arrangement, where a piece of middleware can call another piece of middleware, which in turn can call another, is referred to as a pipeline. You can think of each piece of middleware as a section of pipe – when you connect all the sections, requests flow through one piece into the next.

One of the most common use cases for middleware is for “crosscutting concerns” of your application. These aspects of your application need to occur with every request, regardless of the specific path in the request or the resource requested. These include things like:

  • Logging each request

  • Adding standard security headers to the response

  • Associating a request with the relevant user

  • Setting the language for the current request

In each of these examples, the middleware receives a request, modifies it, and then passes the request on to the next piece of middleware in the pipeline. Subsequent middleware could use the details added by the earlier middleware to handle the request. For example, in figure 2, the authentication middleware associates the request with a user. The authorization middleware uses this detail to verify whether the user has permission to make that specific request to the application.


Figure 2 Example of a middleware component modifying the request for use later in the pipeline. Middleware can also short-circuit the pipeline, returning a response before the request reaches later middleware.


If the user has permission, the authorization middleware passes the request on to the MVC middleware, to allow it to generate a response. If, on the other hand, the user doesn’t have permission, the authorization middleware can short-circuit the pipeline, generating a response directly. It returns the response back to the previous middleware, before the MVC middleware has even seen the request.

A key point to glean from this is that the pipeline is bi-directional. The request passes through the pipeline in one direction until a piece of middleware generates a response, at which point the response passes back through the pipeline in the other direction, passing through each piece of middleware for a second time, until it gets back to the first piece of middleware. Finally, this first/last piece of middleware passes the response back to the ASP.NET Core web server.

 

The HttpContext object

Once the application has finished processing the request, it’ll update the HttpContext with an appropriate response and return it back through the middleware pipeline to the web server. The ASP.NET Core web server converts the representation into a raw HTTP response and sends it back to the reverse proxy, which will forward it to the user’s browser.

 

You define the middleware pipeline in code as part of your initial application configuration in Startup. You can tailor the middleware pipeline specifically to your needs –simple apps may need only a short pipeline, and large apps with a variety of features may use many more middleware. Middleware is the fundamental source of behavior in your application – ultimately the middleware pipeline is responsible for responding to any HTTP request it receives.

The request is passed to the middleware pipeline as an HttpContext object. The ASP.NET Core web server builds an HttpContext object from the incoming request, which passes up and down the middleware pipeline. When you’re using existing middleware to build a pipeline, this is a detail you’ll rarely deal with. Its presence behind the scenes provides a route to exerting extra control over your middleware pipeline.

 

Middleware vs HTTP Modules and HTTP Handlers

The middleware pipeline makes understanding your application far simpler. The pipeline is completely defined in code, specifying which components should run, and in which order.

 

This is all there is to the concept of middleware.

That’s all for this article. For more information, download the free first chapter of ASP.NET Core in Action and see this Slideshare presentation.