In this article we will be exploring Asp.Net Middlewares. On this episode we will explore and dig deep into middleware, what are they and how do they work. What are the different types of middleware and when we should use each.
You can watch the full video on Youtube
You can find the source code on GitHub:
https://github.com/mohamadlawand087/v43-delegates
So what we will cover today:
- What is a Middleware
- Advantages and Disadvantages
- Ingredients
- Diving deep
- 3 types of Middlewares execution
- Built in Middlewares in Asp.Net Core
As always please comment your questions, clarifications and suggestions in the comments down below. Please like, share and subscribe if you like the video. It will really help the channel
What is a Middleware
Middleware is a component assembled in the app pipeline to handle requests and responses. they are chained one after the other so each one will choose to pass the request to the next component or not.
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.
Perform work before and after the next component.
Advantages
- Configuration of every HTTP processing:Essentially, the middleware performs some specific function on the HTTP request or response at a specific stage in the HTTP pipeline before or after the user defined controller.
- Lean application due to the high customisability
- Better Performance / Less memory usage
- Middleware are highly asynchronous
Disadvantages
- Porting complex authorisation / authentication module could be time consuming
- Philosophy of middleware is complicated
- Finding the right middleware to use
Will start by creating a new asp.net core application
dotnet new web -n testApp
Now that we have created our application let us open it in VS Code and examen our application.
We can see we have our startup class and program.cs
In the startup class is where we are doing all of the wiring and configuration for our Asp.Net Core application.
In the Startup Class we have 2 methods
- Configure Services: This is not a mandatory method
- Configure: This is mandatory
Now let us build and run the application and see what do we get, to build the application we will run the following
dotnet build
To run the application
dotnet run
Now let us visit the generated Url and we can see that the response we are getting is hello world no matter what controller/action we add to the url if they don't exist.
Why is that? its because of the way our startup class has been configured out of the box which is to route all requests to a "Hello World."
Now let us examin how the Startup class work and let us understand how Middlewear works.
Will start by having an empty class and will build it up as we go so we can understand how all fits together.
We will remove all of the source code from inside the startup class and will leave the 2 mthods there. So we will have something like this
public class Startup{ public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { }}
Now let us run the application and see what is going to happen
dotnet run
Once the application run, and we visit the Url we can see that we are getting a 404 because our Configure method is empty and we have not added any configuration to our Asp.Net application so it know how to handle the requests, so a 404 response is given.
Now let us fix this by adding some functionality to our startup class, the configure method is we setup middlewares.
Now let us update our configure method with a simple middleweare so we can process any incoming requests
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ // app is an instance of application builder // run method => which takes a delegate function to process the request // we utilise the response and write a message // This is a request delegate which is a dotnet middlewear - inline middlewear app.Run(async c => await c.Response.WriteAsync("Welcome to the App"));}
Now let us run the application and see what do we get
dotnet run
As we can see now we are getting the "Welcome to the App " message when we visite the generated url http://localhost:5000 or any url under the same localhost. No matter requests comes in the inline middlewear that we have created will be able to pick up the request and show the same message on the screen.
The request delegates or the middlewear can be configured in 3 extension methods
- app.Run
- app.Use
- app.Map
Let us delve deep into each one and see how do they differe and when should we use each one
app.Run
- it only recieves a context parameter, it doesn't know about the next middlewear these delegates are called terminal delegates because it ends and terminates the middlewear pipelines
- It is more of a convention to use the Run method to indicate that we are at the end of a pipelines, let us add a new delegate after this app.Run and we will see that it will not work as the first app.Run middlewear has terminated the pipelines if we run it now we can see only the first message is showing
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ // app is an instance of application builder // run method => which takes a delegate function to process the request // we utilise the response and write a message // This is a request delegate which is a dotnet middlewear - inline middlewear app.Run(async c => await c.Response.WriteAsync("Welcome to the App")); app.Run(async c => await c.Response.WriteAsync("Welcome to the App part 2"));}
The main idea of a middlewear is the ability to chain middlewear behind each other to process and create the functionality that we want.
app.Use
with this extension method will allow us to chain middlewares so lets see this in action
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ // middlewear 1 app.Use(async (c, next) => { Console.WriteLine("Order 1"); await c.Response.WriteAsync("I am the first middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2"); }); // middlewear 2 app.Run(async c => await c.Response.WriteAsync("\nI am the second middlewear"));}
As we can see here we have utilised the Use extension method to create our middlewear and chain the second middlewear to it.
Now let us add a new middlewear and let us monitor the flow of execution
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ // middlewear 1 app.Use(async (c, next) => { Console.WriteLine("Order 1"); await c.Response.WriteAsync("I am the first middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2"); }); // middlewear 2 app.Use(async (c, next) => { Console.WriteLine("Order 1a"); await c.Response.WriteAsync("\nI am the second middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2a"); }); // middlewear 3 app.Run(async c => await c.Response.WriteAsync("\nI am the third middlewear"));}
Once we run our application we can see the order of execution is as follow
Console:Order 1Order 1aOrder 2aOrder 2Browser:I am the first middlewearI am the second middlewearI am the third middlewear
Which means we are going throw the middlewear processing in order of execution. the only way we can specify in which order the middlewear are running is by writing them in the right order in the code.
Let us see if we update the middlewares to the following
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ // middlewear 1 app.Use(async (c, next) => { Console.WriteLine("Order 1"); await c.Response.WriteAsync("I am the first middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2"); }); // middlewear 3 app.Run(async c => await c.Response.WriteAsync("\nI am the third middlewear")); // middlewear 2 app.Use(async (c, next) => { Console.WriteLine("Order 1a"); await c.Response.WriteAsync("\nI am the second middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2a"); }); }
We can see here that the second middlewear doesn't get executed as its after the app.Run middlewear which basically terminates the middlewear pipelines.
For this reason ordering the middlewares is really important.
So now let us examine how the pipeline is getting chained
The chainning of the middleware will be following the numbers
- 1 - the request will come
- Logic will excute inside the middleware 1
- middleware 1 will call the next method which will call the next middleware
- 2- middleware 2 is being called
- Logic inside middleware 2 will execute
- middleare 2 will call the next method which will call the next middleware
- 3- middleare 3 is being caled
- Logic inside middleware 3 is being executed
- since there is not next method this will be a terminator middleware and the request will start going back up the stack
- middleware 3 will call middleware 2
- Logic will execute in middleware 2
- middleware 2 will call middleware 1
- middleware 1 will execute the logic
- middleware 1 will return the request to the user
In summary middleare are chained with each other no matter how many middlewares we have they are going to be chainned together and executed in the order they are added.
From the illustration below we can see how middleware nesting works when we chain middleware together. The main idea of having seperate methods (seperate middlewares) is to keep our code clean and to follow the single responsibility principle where every method (middleware) is responsible for only 1 responsibility.
Built-in middleware
ASP.NET Core ships with a lot middleware components built into it which help us utilise ASP.NET to its full potential and removing the need for us to write a lot of the functionalities that we need. Some of the main middlewares that comes with Asp.Net
- Authentication
- Authorisation
- CORS
- MVC
- Rooting
- HTTPS
And so much more.
Building our own middleware
The next step is to move the code from the startup to its own class so we can keep the startup class as clean and simple as possible. The first thing we need to do is create a folder in our root directory called Extensions and inside the extensions folder will create a new class called AppCultureMiddleware.cs
Now let us build our first middleware with extension methods
public class AppCultureMiddleware //: IMiddleware { private readonly RequestDelegate _next; public AppCultureMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context) { var cultureQuery = context.Request.Query["culture"]; if (!string.IsNullOrWhiteSpace(cultureQuery)) { var culture = new CultureInfo(cultureQuery); CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = culture; } // Call the next delegate/middleware in the pipeline await _next(context); } }
Will start by utilising the extention method, in the same folder Extentions let us create a new class called AppCultureMiddlewareExtensions and update it with the following
// Static classpublic static class AppCultureMiddlewareExtensions{ // ASP.NET core builder public static IApplicationBuilder UseAppCulture( this IApplicationBuilder builder) { // initialise the middleware return builder.UseMiddleware<AppCultureMiddleware>(); }}
Now let us update the startup class, inside the ConfigureServices metho with the following
app.UseAppCulture();
Now to test it we can build and run our application
dotnet run
and then visiting the application with the cutlture query string similar to the following
https://localhost:5001/?culture=no
Now let us check the other way to create a middleware, will create a new middleare just to console log the flow of the code. Inside the extensions folder let us create a new class called AppSampleLogsMiddleware.cs this class will implement the IMiddleware interface
public class AppSampleLogsMiddleware : IMiddleware // implementing the interface{ // Required methods to implement the interface correctly public Task InvokeAsync(HttpContext context, RequestDelegate next) { throw new System.NotImplementedException(); }}
We are going to add some logic to our middleware which will log the flow of the middleware.
public class AppSampleLogsMiddleware : IMiddleware // implementing the interface{ // Required methods to implement the interface correctly public async Task InvokeAsync(HttpContext context, RequestDelegate next) { Console.WriteLine("Order 1a"); await context.Response.WriteAsync("\nI am the second middlewear"); // this is responsible for calling middlewear 2 await next(context); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2a"); }}
Now that our middleware is ready we need to update the startup class so our application will recognise it, inside out configureServices we can register our new middleware by adding the following code
public void ConfigureServices(IServiceCollection services){ // we are going to register the middleware into our services collection services.AddTransient<AppSampleLogsMiddleware>();}
Now let us update the Configure method in the startup class to use the middleware by adding the following code
app.UseMiddleware<AppSampleLogsMiddleware>();
Now to utilise this middleware we have 2 ways to register it the first one is to
- Use the Middleware extension method
- Register the Middleware method in the startup class
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ app.UseAppCulture(); // middlewear 1 app.Use(async (c, next) => { Console.WriteLine("Order 1"); await c.Response.WriteAsync("I am the first middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2"); }); app.UseMiddleware<AppSampleLogsMiddleware>(); // middlewear 3 app.Run(async c => await c.Response.WriteAsync("\nI am the third middlewear"));}
app.Map
This extension method is usually used when we want to branch the middleware pipeline, so anytime we want to branch the request into 2 different pipelines we use map.
Each time we use map it will completely break off the original pipeline and everything after that it will not be invoked. Let us see this in action
So Basically when ever we redirect our application to /life the middleweare will be triggered and will execute
public void Configure(IApplicationBuilder app, IWebHostEnvironment env){ // middlewear 1 app.Use(async (c, next) => { Console.WriteLine("Order 1"); await c.Response.WriteAsync("I am the first middlewear"); // this is responsible for calling middlewear 2 await next(); // once middlewear 2 has completed we return to continue the execution // of the first middlewear Console.WriteLine("Order 2"); }); app.Map("/life", lifeHandler); app.UseMiddleware<AppSampleLogsMiddleware>();}private void lifeHandler(IApplicationBuilder app){ app.Run(async context => { Console.WriteLine("I am your life handler"); await context.Response.WriteAsync("I am your life handler"); });}
Now let us run the code
dotnet run
Ad we can see when executing that noting after the map middleware is executing because the map method will be the last one to execute
Another instance pf the map method is to use the mapWhen, which is a conditional based mapping. mapWhen will take a condition and only execute if these conditions are met. Let us update our code to the following
app.MapWhen(c => c.Request.Query.ContainsKey("s"), HandleConditionalRequest);
private void HandleConditionalRequest(IApplicationBuilder app){ app.Run(async context => { Console.WriteLine("I am your conditional handler"); await context.Response.WriteAsync("I am your conditional handler"); });}
This will terminate the middleware pipeline since we are using the app.Run inside the method.
And finally we can use the app.UseWhen which basically allow us to continue utilising our pipeline with something similar to this
app.UseWhen(c => c.Request.Query.ContainsKey("u"), HandleSecondConditionalRequest);
private void HandleSecondConditionalRequest(IApplicationBuilder app){ app.Use(async (context, next) => { Console.WriteLine("I am your second conditional handler"); await context.Response.WriteAsync("I am your second conditional handler"); await next(); });}
FAQs
What is middleware in NET Core interview questions? ›
Middleware is a component (logic code), which gets executed on each HTTP request in the Asp.net Core application. Middleware is injected into the application pipeline to handle request and responses. Each middleware adds or modifies the HTTP request and optionally passes control to the next middleware component.
What is the use of middleware in ASP.NET Core? ›Middleware is software that's assembled into an app 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.
How many types of middleware are there in ASP.NET Core? ›Typically, there will be multiple middleware in ASP.NET Core web application. It can be either framework provided middleware, added via NuGet or your own custom middleware. We can set the order of middleware execution in the request pipeline.
How to write middleware in ASP.NET Core? ›For this, right click on the project or folder where you want to create middleware class and select Add -> New Item. This will open Add New Item popup. Search for word "middleware" in the top right search box as shown below. Select Middleware Class item and give it a name and click on Add button.
What are the 6 types of middleware? ›- Message Oriented Middleware. ...
- Object Middleware. ...
- Remote Procedure Call (RPC) Middleware. ...
- Database Middleware. ...
- Transaction Middleware. ...
- Portals. ...
- Embedded Middleware. ...
- Content-Centric Middleware.
Middleware functions can be divided into three main categories: application-specific, information-exchange and management and support middleware.
What are the 4 functions of middleware systems? ›Data management, application services, messaging, authentication, and application programming interface (API) management are all commonly handled by middleware.
What is the main goal of middleware? ›Middleware is software that lies between an operating system and the applications running on it. Essentially functioning as hidden translation layer, middleware enables communication and data management for distributed applications.
What are the benefits of middleware? ›- Efficient connectivity. Middleware moves real-time information between applications, systems, and platforms.
- Innovative solutions. ...
- Faster development time and scalability. ...
- Easily accessible workplace tools.
We can use more than one middleware on an Express app instance, which means that we can use more than one middleware inside app. use() or app. METHOD() .
What is the difference between middleware and filter? ›
A middleware can run for all requests while filters will only run for requests that reach the EndpointMiddleware and execute an action from an API Controller or a Razor Page. Filters have access to MVC components (eg: ModelState or IActionResults ).
Is ASP.NET Core middleware Singleton? ›Middleware components are only constructed once during the application's lifetime, which means they are singletons within the application. Dependencies injected via the constructor are captured for the application's lifetime.
What is difference between middleware and filters in .NET Core? ›Middleware can be used for the entire request pipeline but Filters is only used within the Routing Middleware where we have an MVC pipeline so Middleware operates at the level of ASP.NET Core but Filters executes only when requests come to the MVC pipeline. Let's understand the difference using the Code Example.
Can we create custom middleware in ASP.NET Core? ›Middleware is software that's assembled into an app pipeline to handle requests and responses. ASP.NET Core provides a rich set of built-in middleware components, but in some scenarios you might want to write a custom middleware. This topic describes how to write convention-based middleware.
What is middleware in REST API? ›API (application programming interface) middleware provides tools developers can use to create, expose and manage APIs for their applications - so that other developers can connect to them. Some API middleware includes tools for monetizing APIs - enabling other organizations to use them, at cost.
What is the difference between middleware and API? ›API refers to callable services, while middleware refers to the product that does the integration work in the integration ecosystem. Go! Middleware is logical Software System that provides capabilities to other software applications, databases etc to be integrated.
Is middleware a database? ›Database access services are often characterised as middleware. Some of them are language specific implementations and support heterogeneous features and other related communication features. Examples of database-oriented middleware include ODBC, JDBC and transaction processing monitors.
Why is it called middleware? ›Why is it called middleware? The name middleware stems from the fact that it is the software that sits between the client-side requests on the front end and the back-end resource being requested. A client can make a request with network-based interactions.
What are the two types of middleware models? ›There are two types of middleware models: logical and physical. The logical middleware model depicts how information moves throughout the enterprise conceptually. In contrast, the physical middleware model depicts both the actual method of information movement and the technology employed.
Is middleware an object? ›Object-based middleware is runtime software that enables objects (components) to work cooperatively with a container program or another object, even if the software is distributed across multiple computers.
What is the disadvantage of middleware? ›
- Slow computer for application server.
- slow connection between applications server and database server.
Middleware function requestTime
Also, the callback function of the root path route uses the property that the middleware function adds to req (the request object). When you make a request to the root of the app, the app now displays the timestamp of your request in the browser.
Middleware is software that different applications use to communicate with each other. It provides functionality to connect applications intelligently and efficiently so that you can innovate faster.
How do you handle middleware? ›- Execute any code.
- Make changes to the request and the response objects.
- End the request-response cycle.
- Call the next middleware function in the stack.
Middleware stands between web applications and web services that natively can't communicate and often are written in different languages/frameworks. One such example is OWIN middleware for . NET environment, before owin people were forced to host web apps in a microsoft hosting software called IIS .
Is middleware the same as application server? ›Middleware is more general than Application Server. An application server is one type of middleware. The fact is that the term middleware, when applied to distributed computing is rather vague and can be applied to any piece of software that exists between the server and client.
Can we run multiple middleware at a time? ›To assign middleware to a route you can use either single middleware (first code snippet) or middleware groups (second code snippet). With middleware groups you are assigning multiple middleware to a route at once. You can find more details about middleware groups in the docs.
Can you apply two middleware single route? ›Middleware groups may be allocated to routes and controller activities with the same syntax as a single middleware. Middleware groups make it more helpful to allot numerous middleware to a route at once.
How do I pass multiple middleware? ›- Route::get('/', function () {
- // ...
- })->middleware([First::class, Second::class]);
Middleware is a thing of the past. It was an old-fashion system-specific software that allowed data to move from point A to point B for retailers back in the day.
Is middleware same as controller? ›
What's immediately confusing is that a controller can be considered a type of middleware. (And to add to the confusion, "controllers" are sometimes referred to as "route handlers".) But middleware - compared to controllers - handles HTTP-specific concerns as well as concerns that are common to every (or most) request.
What is the difference between middleware & webservices? ›Therefore web service can be considered as an online API. Middleware allows to communicate with distributed application components located in several computers (Simply links the components located in various machines in order to get the full application capabilities).
Is DbContext scoped or singleton? ›The AddDbContext extension method registers DbContext types with a scoped lifetime by default.
What is the difference between app run and app use middleware in .NET Core? ›The difference is, middleware defined using app. Use may call next middleware component in the pipeline. On the other hand, middlware defined using app. Run will never call subsequent middleware.
What is default middleware in .NET Core? ›Middleware in ASP.NET Core controls how our application responds to HTTP requests. It can also control how our application looks when there is an error, and it is a key piece in how we authenticate and authorize a user to perform specific actions.
What are the three components of database middleware? ›Middleware components, such as, schedulers, load balancers and optimizers have been used for performance scaling of workloads on LAN-based database clusters, and/or for data availability.
What is the difference between firmware and middleware? ›The main difference between firmware and middleware is that the firmware is a type of software that allows controlling the device's hardware while the middleware is a software that provides services to software applications beyond those available from the operating system.
What is middleware in 3 tier architecture? ›Middleware is a kind of software that links programs running on different platforms, transmitting messages and data. It plays an important role in 3-tier architecture.
Can we use middleware in controller? ›We can also assign the middleware to the controller's routes within your route files. There are various ways of assigning the middleware to the controller: Assigning the middleware to the controller in the web.
Which package provides middleware in ASP.NET Core? ›Middleware can be built-in as part of the . NET Core framework, added via NuGet packages, or can be custom middleware. These middleware components are configured as part of the application startup class in the configure method.
How do you inject service in middleware? ›
- Inject the service into the middleware's Invoke or InvokeAsync method. Using constructor injection throws a runtime exception because it forces the scoped service to behave like a singleton. ...
- Use Factory-based middleware.
Common middleware examples include database middleware, application server middleware, message-oriented middleware, web middleware, and transaction-processing monitors.
What is the main use of middleware? ›It provides functionality to connect applications intelligently and efficiently so that you can innovate faster. Middleware acts as a bridge between diverse technologies, tools, and databases so that you can integrate them seamlessly into a single system. The single system then provides a unified service to its users.
What is the difference between API and middleware? ›API refers to callable services, while middleware refers to the product that does the integration work in the integration ecosystem. Go! Middleware is logical Software System that provides capabilities to other software applications, databases etc to be integrated.
What is an example of middleware? ›Examples of database-oriented middleware include ODBC, JDBC and transaction processing monitors. Distributed computing system middleware can loosely be divided into two categories—those that provide human-time services (such as web request servicing) and those that perform in machine-time.
Where do I put middleware in NET Core? ›We set up the middleware in ASP.NET using the Configure method of our Startup class. Inside the Configure() method, we will invoke the extension methods on the IApplicationBuilder interface to add middleware.
How to test ASP.NET Core middleware? ›- Build and start a host that uses TestServer.
- Add any required services that the middleware uses.
- Add a package reference to the project for the Microsoft. AspNetCore. TestHost NuGet package.
- Configure the processing pipeline to use the middleware for the test. C# Copy.
While a platform allows a software to run and a framework is more focused on software design, a middleware will provide services for your application.
What are two basic kinds of database middleware? ›There are two basic kinds of the database middleware – native database and database-generic. The native database middleware is known as a proprietary access mechanism that's used for a certain database server.