Middleware

As per the ASP.NET Core documentation (available at https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware/?tabs=aspnetcore2x), middleware is a software that is assembled into an application pipeline to handle requests and responses. Each component:

  • Chooses whether to pass the request to the next component in the pipeline
  • Can perform work before and after the next component in the pipeline is invoked

Request delegates are used to build the request pipeline. The request delegates handle each HTTP request. Request delegates are configured using the Run, Map, and Use extension methods. An individual request delegate can be specified inline as an anonymous method (called inline middleware), or it can be defined in a reusable class. These reusable classes and inline anonymous methods are middleware. Each middleware component in the request pipeline is responsible for invoking the next component in the pipeline, or short-circuiting the chain as required.

The classical diagram of middleware in the pipeline, which is available at Microsoft's official ASP.NET Core documentation site, is shown here, with the added detail of steps, which makes it extremely lucid. What happens in Step 3 is shown in the following diagram:

Lets look at it in a step-by-step approach:

  1. Step 1: The request is received by Middleware 1. The pseudo code of Middleware 1 in the Configure(IApplicationBuilder app, IHostingEnvironment env) method of Startup.cs would be UseMiddleware1();, as it processes the request and invokes the next middleware. Recall that we discussed the Use, Map, and Run methods in brief in Chapter 3Building Our First .NET Core Game Tic-Tac-Toe.
  2. Step 2: The code/logic of Middleware 1 is executed.
  3. Step 3RequestDelegatenext(); is executed, which invokes the next middleware.
  4. Step 4: The code/logic of Middleware 2 is executed. The pseudo code of Middleware 2 in the Configure(IApplicationBuilder app, IHostingEnvironment env) method of Startup.cs would be UseMiddleware2();.
  5. Step 5RequestDelegatenext();  is executed, which invokes the next middleware.
  6. Step 6: The code/logic of Middleware 3 is executed. Based on this diagram, the request is handled here, but we can chain in as much middleware as we need. The pseudo code of Middleware 3 in the Configure(IApplicationBuilder app, IHostingEnvironment env) method of Startup.cs can be either UseMiddleware3();, which doesn't call next();, or it can simply be RunMiddleware3();, which short-circuits the pipeline. Normally, this would be the MVC Routing middleware, which would route the request to the MVC Controller, which processes the request and returns the response.
  7. Step 7: As the request is handled in the last step, the response is returned to Middleware 2, which can do further processing of the response and return it.
  8. Steps 8 and 9: Likewise, the response is processed in Middleware 2 and Middleware 1.
  9. Step 10: The processed response from all middleware is returned.

If we look at the Configure(IApplicationBuilder app, IHostingEnvironment env) method in our Startup.cs class, we see the following code, which comes with the default MVC template:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}

app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute(name: "default",template: "
{controller=Home}/{action=Index}/{id?}");
});
}

They say that a picture is worth a thousand words, so to understand this code in the context of the pipeline, if we draw the diagram for a non-developer environment (that is, env.IsDevelopment() == false;), here is roughly what it would look like:

We can see that, based on the code for the else case, the request first goes through the exception middleware through app.UseExceptionHandler("/Home/Error");. This is done to ensure that if any part of the code encounters the exception in the pipeline, it is handled by the exception handler, so it's kept first. From the diagram, we can note that during the request processing, the middleware does nothing, but just invokes the next middleware in the chain. This can be seen from the ASP.NET Core source code, which is freely available for everyone to see and learn from GitHub (https://github.com/aspnet). I would highly encourage readers to browse the code and see the implementation for a better understanding of the way things have been implemented by the ASP.NET Core team.

Next in line is the static file middleware, which serves static files such as css, js, images, and so on placed in the wwwroot folder. These should be served fast as it makes sense to keep this middleware early in the pipeline. If a request for a static file comes, the static file middleware serves the request and short-circuits the pipeline, so that other unnecessary code is not executed while serving the static file contents. This is configured through app.UseStaticFiles();. Then comes the MVC routing, which routes the incoming request to its desired controller action. We see that there are a number of items that are executed in this middleware. We will go into detail concerning each of these items in later sections and chapters, but the important stuff to note here is that the request is served from the controller action and then routed back through the same pipeline. The static file middleware has no role while a non-static file request is being served, and that becomes evident from the diagram. If there is an exception, it would be handled by the exception handler and the response is served back.

The first app.Run delegate terminates the pipeline. That is, after this, even if you add any further middleware or code, it will not be executed. Multiple request delegates or middleware can be chained using app.Use. The next parameter represents the next delegate in the pipeline. We can short-circuit the pipeline by not invoking the next action. Never call next.Invoke after the response has been sent to the client. Changes to HttpResponse after the response has started will throw an exception. The order in which middleware components are added in the Configure method defines the order in which they are invoked on the requests, and the reverse order for the response. 

Hopefully, by now we have a relatively good understanding of the ASP.NET Core pipeline and middleware. Before we write middleware of our own and learn how to plug it into our pipeline, let's first learn about Dependency Injection, as it will be used extensively in whatever ASP.NET Core application that we write.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.132.194