What is the difference between IApplicationBuilder.Use() and IApplicationBuilder.Run() C# Asp.net Core?

We can configure middleware in the Configure method of the Startup class using IApplicationBuilder instance. The two primary methods for adding middleware are Run() and Use(), each serving different purposes in the middleware pipeline.

Run() is an extension method that adds a terminal middleware to the application's request pipeline, meaning it terminates the pipeline and does not call the next middleware. Use() allows middleware to pass control to the next component in the pipeline.

Syntax

Following is the syntax for the Run() method −

public static void Run(this IApplicationBuilder app, RequestDelegate handler)

Following is the syntax for the Use() method −

public static IApplicationBuilder Use(this IApplicationBuilder app, 
    Func<RequestDelegate, RequestDelegate> middleware)

The RequestDelegate signature is −

public delegate Task RequestDelegate(HttpContext context);

Using Run() Method

Run() creates terminal middleware that ends the request pipeline. Only one Run() middleware will execute per request −

Example

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

public class Startup {
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        app.Run(async (context) => {
            await context.Response.WriteAsync("Hello World!");
        });
        // Any middleware after Run() will never execute
    }
}

Multiple Run() Methods

When multiple Run() methods are configured, only the first one executes −

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

public class Startup {
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        app.Run(async (context) => {
            await context.Response.WriteAsync("1st Middleware");
        });
        
        // This will never be executed
        app.Run(async (context) => {
            await context.Response.WriteAsync(" 2nd Middleware");
        });
    }
}

The output of the above code is −

1st Middleware

Using Use() Method

Use() allows middleware to pass control to the next component using the next parameter. This enables building a middleware pipeline −

Example

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

public class Startup {
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        app.Use(async (context, next) => {
            await context.Response.WriteAsync("1st Middleware! ");
            await next(); // Call next middleware
        });
        
        app.Run(async (context) => {
            await context.Response.WriteAsync("2nd Middleware");
        });
    }
}

The output of the above code is −

1st Middleware! 2nd Middleware

Middleware Pipeline Flow

The following example demonstrates how middleware executes in sequence and can perform actions both before and after calling next()

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;

public class Startup {
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        app.Use(async (context, next) => {
            await context.Response.WriteAsync("Before First -> ");
            await next();
            await context.Response.WriteAsync(" -> After First");
        });
        
        app.Use(async (context, next) => {
            await context.Response.WriteAsync("Before Second -> ");
            await next();
            await context.Response.WriteAsync(" -> After Second");
        });
        
        app.Run(async (context) => {
            await context.Response.WriteAsync("Terminal Middleware");
        });
    }
}

The output of the above code is −

Before First -> Before Second -> Terminal Middleware -> After Second -> After First

Run() vs Use() Comparison

Run() Use()
Terminal middleware - ends the pipeline Non-terminal middleware - can call next
No next parameter Has next parameter to invoke next middleware
Only one Run() executes per request Multiple Use() can execute in sequence
Should be placed at the end of pipeline Can be placed anywhere in pipeline

Conclusion

Run() creates terminal middleware that ends the request pipeline, while Use() allows middleware to pass control to the next component. Use Use() for building middleware chains and Run() for final request handling.

Updated on: 2026-03-17T07:04:36+05:30

6K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements