Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Understand Run, Use, Map and MapWhen to Hook Middleware in HTTP Pipeline of ASP.NET5

0.00/5 (No votes)
6 Jan 2016 2  
Understand Run, Use, Map and MapWhen to hook middleware in HTTP pipeline of ASP.NET5

Introduction

It’s more transparent to hook middleware in ASP.NET 5 application compared to prior versions. We can use Run, Map and Use extension method to hook any middleware in between HTTP pipeline. In this example, we will understand the difference among them with an example.

Run Extension

The nature of Run extension is to short circuit the HTTP pipeline immediately. It is a shorthand way of adding middleware to the pipeline that does not call any other middleware which is next to it and immediately return HTTP response. So, it’s recommended to use Run extension to hook middleware at last in HTTP pipeline. Let’s see how Run behaves in action.

public void Configure(IApplicationBuilder app)
    {
        app.UseMvc();
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Return From Run.");
        });
        app.Run(async context => {
            await context.Response.WriteAsync("This is second Run.");
        });
    }

Here, we hook two Run functions next to next and while running, we are getting only response from first Run.

That implies the first run has short circuit the HTTP request and sends response from itself without forwarding to next middleware.

Use Extension

In case of Use extension, there is a chance to pass next invoker, so that HTTP request will be transferred to the next middleware after execution of current Use if there next invoker is present. In this example, we have attached next invoker with Use extension, so that HTTP call will get transferred to next middleware even we tried to return:

public void Configure(IApplicationBuilder app)
    {
        app.UseMvc();
        app.Use(next=> async context =>
        {
            await context.Response.WriteAsync("Return From Use.");
            await next.Invoke(context);
        });
        app.Run(async context => {
            await context.Response.WriteAsync("This is from Run.");
        });
    }

HTTP response within Use extension. Here is the output of the above code fragment.

We are seeing that both strings from Use and Run have printed as output. Here, we should notice that we are forwarding the HTTP request to next level by adding the following line.

await next.Invoke(context);

Otherwise, Use extension will not escalate HTTP request and will behave as Run Extension method.

app.Use(next=> async context =>
   {
       await context.Response.WriteAsync("Return From Use.");
   });

Once we remove the next.Invoker(), we are getting output only from Use Extension.

Map Extension

Map extensions are used as convention for branching the pipeline. We can hook delegate to Map extension to push it to HTTP pipeline. Map simply accepts a path and a function that configures a separate middleware pipeline. In this example, we will hook one middleware/delegate to HTTP pipeline using Map extension.

private static void MyDelegate(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Returning from Map");
        });
    }
    public void Configure(IApplicationBuilder app)
    {
        app.UseMvc();
        app.Map("/MyDelegate", MyDelegate);
    }

In Map extension, we have hooked MyDelegate delegate with “/MyDelegate” path. So, when user will perform any HTTP call to the same path, the delegate function will get triggered.

The message has returned from delegate function. One fact we should notice that, Map takes delegate and within delegate, it allows to use both Run and Use depending on the requirement. MapWhen Extension supports path-based mapping, the MapWhen method supports predicate-based middleware branching, allowing separate pipeline to be constructed in a flexible way. In this example, we have mapped middleware execution with the presence of query string “q” in URL.

private static void HandleQuery(IApplicationBuilder app)
    {
        app.Run(async context =>
        {
            await context.Response.WriteAsync("Return from HandleQuery");
        });
    }
    public void Configure(IApplicationBuilder app)
    {
        app.UseMvc();
        //Execute when "q" is there in query string
        app.MapWhen(context => {
            return context.Request.Query.ContainsKey("q");
        }, HandleQuery);
        //Return response for other request
        app.Run(async context =>
        {
            await context.Response.WriteAsync("From Run extension");
        });
    }

This type of branching is very useful when we have a separate handler to handle a certain request. For example, in some scenarios, we may want to bypass AJAX call to some handler like this:

private void HandleAJAX(IApplicationBuilder app)
{
}
public void Configure(IApplicationBuilder app)
{
    app.UseMvc();
    app.MapWhen(ctx =>
ctx.Request.Headers.Get("X-Requested-With") == "XMLHttpRequest", HandleAJAX);
}

Here, we are checking for “X-Request-With” header in the current HTTP request. If the header is present, then the request is AJAX request and for that HandleAJAX handler will take care of.

Summary

Middleware are a well known feature in ASP.NET which was incepted in form of HTTP Handler and HTTP module in the early Web Forms days followed by Delegating handler and Middleware (MVC6) in MVC framework. In this tip, we have learned to use Run, Use, Map and MapWhen extension method to hook middleware in ASP.NET 5/MVC6 HTTP pipeline. Those methods are ready to accept custom middleware too. Developers can easily create their own middleware to inject additional functionality in HTTP pipeline.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here