lets understand how to use branching(MAP and MAP WHEN) in ASP.NET Core middleware

lets understand how to use branching(MAP and MAP WHEN) in ASP.NET Core middleware

·

6 min read

I will explain how to use the Map method to create different paths for the request based on some condition. I will also show you the difference between the Use and the Run methods, and how they affect the execution of the middleware components. I will use a simple example to illustrate the concept and the code. By the end of this post, you will have a better understanding of how branching works in middleware and how to use it effectively.

lets understand few basics about the concepts

What is middleware? Middleware is a piece of code that sits between the request and the response in a web application. It can do things like logging, authentication, error handling, and so on. Middleware can be added to the pipeline, which is the sequence of middleware components that process the request and generate the response.

Now, what is branching? Branching is a way of creating different paths for the request to follow based on some condition. For example, you can branch the request based on the URL, the HTTP method, the content type, and so on. Branching can be done using the Map method, which takes a condition and a delegate as parameters. The delegate is a function that defines the middleware components for the branch.

So, what is the difference between the Use and the Run methods? The Use method adds a middleware component to the pipeline that can either pass the request to the next component or end the request. The Run method adds a middleware component that always ends the request and returns the response. The Run method should be the last one in the pipeline or the branch.


lets consider below code first

below is snippet of the code

app.UseAuthorization();

app.Use(async (context, next) =>
{
    Console.WriteLine($"Logic before executing the next delegate in the Use method");
    await next.Invoke();
    Console.WriteLine($"Logic after executing the next delegate in the Use method");
});
app.Map("/usingmapbranch", builder =>
{
    builder.Use(async (context, next) =>
    {
        Console.WriteLine("Map branch logic in the Use method before the next delegate");

        await next.Invoke();
        Console.WriteLine("Map branch logic in the Use method after the next delegate");
    });
    builder.Run(async context =>
    {
        Console.WriteLine($"Map branch response to the client in the Run method");
        await context.Response.WriteAsync("Hello from the map branch.");
    });
});
app.MapWhen(context => context.Request.Query.ContainsKey("testquerystring"), builder =>
{
    builder.Run(async context =>
    {
        await context.Response.WriteAsync("Hello from the MapWhen branch.");
        app.Run(async context =>
{
    Console.WriteLine($"Writing the response to the client in the Run method");
    await context.Response.WriteAsync("Hello from the middleware component.");
});
    });
});

Understanding MAP

now lets understand , how the this code would behave if called localhost:7281/usingmapbranch

above would be response when we visit above link , lets understand

Here, we can see the messages from the Use method before the branch, and the messages from the Use and Run methods inside the Map branch. We are not seeing any message from the Run method outside the branch. It is important to know that any middleware component that we add after the Map method in the pipeline won’t be executed. This is true even if we don’t use the Run middleware inside the branch.

Why is that? Well, because the Map method creates a separate pipeline for the branch, and the request is diverted to that pipeline if the condition is met. The request never goes back to the original pipeline, so any middleware component that comes after the Map method is ignored. The Run method outside the branch is never reached, because the request is either handled by the Run method inside the branch, or by some other middleware component before the Map method.

This is how branching works in middleware. It allows us to create different logic for different scenarios, but we have to be careful about the order of the middleware components and the use of the Run method. If we want to execute some middleware component after the branch, we have to use another Map method with the opposite condition, or use some other branching technique.


Understanding MAP WHEN

what is MapWhen and how it is different from Map ?. MapWhen is another way of creating branches in middleware, but it is more flexible than Map. MapWhen takes a predicate and a delegate as parameters. The predicate is a function that evaluates the request and returns a boolean value. The delegate is a function that defines the middleware components for the branch. MapWhen creates a branch only if the predicate returns true.

For example, suppose you want to create a branch for the requests that have a query string with the key “name”. You can use MapWhen like this:

app.MapWhen(context => context.Request.Query.ContainsKey("name"), branch =>
{
    // Use a middleware component that greets the user by name
    branch.Run(async context =>
    {
        var name = context.Request.Query["name"];
        await context.Response.WriteAsync($"Hello, {name}!");
    });
});

This code will create a branch that will handle the requests like /?name=Bob or /hello?name=Alice. It will return a plain text response with “Hello, Bob!” or “Hello, Alice!” respectively. However, it will not handle the requests like / or /hello, because they do not have a query string with the key “name”. Those requests will be passed to the next middleware component in the pipeline.

The difference between MapWhen and Map is that MapWhen can use any condition to create a branch, while Map can only use the request path. MapWhen is more powerful and flexible, but also more complex and error-prone. You have to be careful about the logic of the predicate and the delegate, and make sure they do not conflict with each other or with the rest of the pipeline.


Final words

In this blog post, I have explained how to use branching in ASP.NET Core middleware. I have shown you how to use the Map method to create different paths for the request based on the request path. I have also shown you the difference between the Use and the Run methods, and how they affect the execution of the middleware components. I have used a simple example to illustrate the concept and the code. I have also explained what is MapWhen and how it is different from Map. MapWhen is another way of creating branches in middleware, but it is more flexible than Map. MapWhen can use any condition to create a branch, while Map can only use the request path.

I hope this blog post has helped you understand how branching works in middleware and how to use it effectively. Branching is a powerful technique that allows you to create different logic for different scenarios, but you have to be careful about the order of the middleware components and the use of the Run method. If you want to execute some middleware component after the branch, you have to use another Map method with the opposite condition, or use some other branching technique.

If you have any questions or feedback, please leave a comment below. I would love to hear from you. Thank you for reading!