Middleware in ASP.Net Core – part II

Tags: ,

Few days ago I wrote a short tutorial about middleware in ASP.Net Core and I promised to continue the topic, since there are some concepts that I didn’t cover. In the mentioned first tutorial I tried to describe what a middleware pipeline is, why middleware order is important and the importance of the next() delegate. In the second part I will focus more on the Use()Run() and Map() methods that we can use when setting up the middleware pipeline of an ASP.Net Core application.

Technically speaking Use()Run() and Map() are extension methods on Microsoft.AspNetCore.Builder.IApplicationBuilder instances. If you look them up, you’ll see something like this:


public static IApplicationBuilder Use(this IApplicationBuilder app, 
    Func<HttpContext, Func<Task>, Task> middleware);

So they are fairly simple but powerful so it’s important when to use them.

We already took a short look into app.Use()deploying an Angular application together with ASP.Net Core in the previous article and we saw that we can use this method when we want to add some basic configurations to the middleware pipeline. We did this when , to make sure that unresolved routes by Kestrel are passed to the front end, where Angular would take care about routing. Generally you can use this method for such simple tasks, or perform some basic logging, or inspect the response before it leaves the server and so on. For more complicated tasks, I would advise to create your own middleware.

There is, however one important thing to note: if you don’t use the next() delegate, making sure that you pass the request/response to the next middleware in the pipeline, then you will short-circuit the entire middleware pipeline. The request/response simply won’t go any further. As a reminder, here is also a code sample:


app.Use(async (context, next)
    {
        await next();
        if (context.Response.StatusCode == 404 && !Path.HasExtension(context.Request.Path.Value))
            {
                context.Request.Path = "/index.html";
                await next();
            }
    })

Notice that we used next() two times: the first time it passes the request to the next middleware, while the second time it passes the response to the next middleware.

The app.Run() method is designed to execute something. This method does also short-circuit the pipeline so in rare cases where you’ll use it make sure that you do it at the end of the pipeline. That’s also the reason why there is no next() in app.Run(). I always like to give practical examples so here’s also an interesting code sample that demonstrates this.


public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {

        app.Use(async (context, next) =>
            {
                await context.Response.WriteAsync("<p>First middleware using app.Use</p>");
                await next();
            });

        app.Run(async context =>
            {

                await context.Response.WriteAsync("<p>Middleware using app.Run</p>");

            });

        app.Use( async (context, next) => {
            await context.Response.WriteAsync("<p>Second middleware using app.Use</p>");
            await next();

            });

       app.UseMvc();
    }

So we have an app.Use(), then an app.Run() and finally an app.Use() again. Guess the outcome!

As you can see, the last app.Use() middleware is not executed anymore, since the pipeline was terminated after app.Run(). If we simply cut the app.Run() middleware and paste it after the last app.Use() middleware, the outcome will be totally different:

Last but not least, app.Map() is used as a convention for branching the pipeline. Map branches the request pipeline based on matches of the given request path. If the request path starts with the given path, the branch is executed. That’s why you will often use this type of middleware  when you have a separate handler to handle a certain request. For example, in some scenarios, we may want to bypass a controller or something similar.

That’s the basic theory about middleware in ASP.Net Core. If you’re not totally familiar with these concepts, i strongly advise you to create a new ASP.Net Core project and simply play around with different middleware, because theory without practice will never take you very far in your career. If you found these tutorials useful, feel free to share them with your friends and network. If you have questions or simply want to add something, don’t be shy and hit me with a comment 🙂 Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *