In the previous example there was only one branch in the middleware. The middleware flow will always come from A to B. There will not be always the same scenario. We can also divert the flow of middleware on basis of input request.
There could be two type branches: branches that rejoin the main pipeline, and branches that don’t
Example of non-rejoining branch in middleware
This can be done using the Map or MapWhen method. Map is used for specifying a branch based on the request path. MapWhen gives us more control on the input request. We can specify a predicate on the HttpContext to decide whether to branch or not.
Here is the demo code for this example
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using System.Diagnostics; namespace MiddleWare_Sample { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { //Middleware A app.Use(async (context, next) => { Debug.WriteLine("A (before)"); await next(); Debug.WriteLine("A (after)"); }); app.Map( new PathString("/emp"), a => a.Use(async (context, next) => { Debug.WriteLine("B (before)"); await next(); Debug.WriteLine("B (after)"); })); app.Run(async context => { Debug.WriteLine("C"); await context.Response.WriteAsync("Hello world"); }); } } }
In the above code, if the browser URL will be https://localhost:44338/ then middleware flow will be
if the URL will be https://localhost:44338/emp then flow will be like this
in the above request response will be 404 (Not found). This is because the B middleware calls next(), but there’s no next middleware, so it falls back to returning a 404 response. To solve this, we could use Run instead of Use, or just not call next().
Example of Rejoining branch in middleware
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using System.Diagnostics; namespace MiddleWare_Sample { public class Startup { // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app) { //Middleware A app.Use(async (context, next) => { Debug.WriteLine("A (before)"); await next(); Debug.WriteLine("A (after)"); }); app.UseWhen( context => context.Request.Path.StartsWithSegments(new PathString("/emp")), a => a.Use(async (context, next) => { Debug.WriteLine("B (before)"); await next(); Debug.WriteLine("B (after)"); })); app.Run(async context => { Debug.WriteLine("C"); await context.Response.WriteAsync("Hello world"); }); } } }
If we run the above code, if the path will be https://localhost:44338 then output will be
If the path will be https://localhost:44338/emp then out put will be like this
This is the complete example of middleware with demo. I hope it will be useful to understand the concept of middleware.