'Use Middleware for some controllers

In my ASP Net Core application I need to apply a custom Middleware only for specific controller.

I found this example

app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
{
    app.UseMiddleware();
});

Is this the correct way?

And how can I check if the request path Contains a specific path instead of starts with?



Solution 1:[1]

As this answer suggests if you require context of MVC you should prefer filters to middleware.

Also here you can find and example how to apply filters to the specific controller.

Solution 2:[2]

"Close" or "Yes".

You have

 app.UseMiddleware();

You most likely want to specify ~which middleware to use. See "MyMiddlewareOne" example below.

Below is tested with Asp.Net Core 3.1. ( I think I was at 3.1.407, but 3.1 or above should be ok )

simple version:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;


public class Startup
{

    public void Configure(ILogger<Startup> logger, IApplicationBuilder app, IWebHostEnvironment env)

    {


        app.UseRouting();

        app.UseAuthentication();


        app.UseWhen(context => context.Request.Path.StartsWithSegments("/api"), appBuilder =>
        {
            appBuilder.UseMiddleware<MyMiddlewareOne>();
        });

        app.UseEndpoints(endpoints =>
        { blah blah blah } );



    }
}

Now, you should be careful on how complex you make the rules.

But you can do something like this:

[ApiController]
[Route("apiwideopen/[controller]")]
public class WeatherForecastController : ControllerBase
{
}

[Route("apisecure/[controller]")]
[ApiController]
public class MyNeedsToBeSecureController : ControllerBase
{
}



        app.UseWhen(context => context.Request.Path.StartsWithSegments("/apisecure"), appBuilder =>
        {
            appBuilder.UseMiddleware<MyMiddlewareOne>();
        });

You can also do this to encapsulate rules.

        app.UseWhen(context => this.CheckMoreAdvancedRules(context), appBuilder =>
        {
            appBuilder.UseMiddleware<MyMiddlewareOne>();
        });



    private bool CheckMoreAdvancedRules(Microsoft.AspNetCore.Http.HttpContext ctx)
    {
        bool returnValue = false;

        if (null != ctx && ctx.Request.Path.StartsWithSegments("/api"))
        {
            returnValue = true;
        }

        if(!returnValue)
        {
            /* do whatever you want here */
            /* if the moon is blue at midnight (then) returnValue = true; */
        }

        return returnValue;
    }

Lastly, you want to pay attention between

"MapWhen" and "UseWhen"

See:

Registering a middleware while using MapWhen for branching to run it just for a set of endpoints

also see this article:

https://www.devtrends.co.uk/blog/conditional-middleware-based-on-request-in-asp.net-core

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Bohdan Stupak
Solution 2