Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is ASP.NET Core executing a custom middleware only once?

I have an ASP.NET Core with the following controller that accepts a POST request:

[Route("api/v1/tenants/tests")]
public class TestsController : Controller
{
    [HttpPost]       
    public IActionResult Post(string tenantId)
    {
        return Ok();
    }
}

I have developed a 'null' middleware to test things out. It is defined in the Configure method of the Startup.cs file:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
     if (env.IsDevelopment())
     {
         app.UseDeveloperExceptionPage();
     }

     app.UseMvc();

     app.Use(async (context, next) =>
     {
         // Forward to the next one.
         await next.Invoke();
     });
}

Question

When I call the controller via Postman, the initial call to the POST method goes successfully through the middleware and then to the Controller. However, the following calls directly go to the Controller, skipping the middleware entirely. Why is that?

like image 864
Kzrystof Avatar asked Oct 02 '18 16:10

Kzrystof


People also ask

Is ASP.NET Core middleware Singleton?

ASP.NET Core uses a single instance of a middleware component to process multiple requests, so it is best to think of the component as a singleton. Saving state into an instance field is going to create problems when there are concurrent requests working through the pipeline.

Why do we need custom middleware in .NET Core?

Each middleware component in ASP.NET Core Application can perform some operations before and after calling the next component using the next method. A middleware component in ASP.NET Core Application can also decide not to call the next middleware component which is called short-circuiting the request pipeline.

How does ASP.NET Core middleware work?

Middleware in ASP.NET Core controls how our application responds to HTTP requests. It can also control how our application looks when there is an error, and it is a key piece in how we authenticate and authorize a user to perform specific actions.

What is the default order of invoking middleware in the request pipeline?

UseRouting , the Routing middleware runs at the beginning of the pipeline by default. For more information, see Routing. The order that middleware components are added in the Program. cs file defines the order in which the middleware components are invoked on requests and the reverse order for the response.


2 Answers

The middlewares must be set up before calling app.UseMvc().

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
     if (env.IsDevelopment())
     {
         app.UseDeveloperExceptionPage();
     }

     app.Use(async (context, next) =>
     {
         // Forward to the next one.
         await next.Invoke();
     });

     // !! Have to be called after setting up middleware !!
     app.UseMvc();
}

This information is present in the documentation but I was not aware that it was applicable to custom middlewares as well:

The order that middleware components are added in the Startup.Configure method defines the order in which the middleware components are invoked on requests and the reverse order for the response. The order is critical for security, performance, and functionality.

The following Startup.Configure method adds middleware components for common app scenarios:

1 - Exception/error handling

2 - HTTP Strict Transport Security Protocol

3 - HTTPS redirection

4 - Static file server

5 - Cookie policy enforcement

6 - Authentication

7 - Session

8 - MVC

Update

In ASP.Net Core 3.0, you need to add your middleware before MapControllers()

 app.UseEndpoints(endpoints =>
 {
     endpoints.MapControllers();
 });
like image 118
Kzrystof Avatar answered Oct 18 '22 01:10

Kzrystof


Startup.Configure() is executed once during app startup. It is used to make preparations for the application, it is not executed with every call. You can however use it to setup a middleware that is executed with every call. The microsoft documentation for asp.net core application startup contains a few examples both Configure and ConfigureServices.

like image 45
Dirk Trilsbeek Avatar answered Oct 18 '22 02:10

Dirk Trilsbeek