Search code examples
c#asp.net-core-webapimiddlewareasp.net-core-middleware

Modifying `Request.Path` via middleware in an ASP.NET Core Web API project does not change the controller/action used


I have a small sandbox application based on the ASP.NET Core Web API template where I am attempting to modify the controller/action to be used based on a custom header and to facilitate this I am replacing the value of the context.Request.Path property.

However, despite confirming via debugging that the middleware is running, that the conditions for replacement are being met and that the value of Request.Path have been changed, the application is still using the controller and action that would have been used should the path have remain unchanged.

The configuration of the application is:

using Sandbox.Middleware;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseMiddleware<ModifyControllerMiddleware>();

app.UseHttpsRedirection();
app.UseAuthorization();

app.MapControllers();

app.Run();

And the middleware itself:

namespace Sandbox.Middleware
{
    public class ModifyControllerMiddleware
    {
        private readonly RequestDelegate _next;

        public ModifyControllerMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            switch (context.Request.Headers["x-intercept"])
            {
                case "1":
                    context.Request.Path = "/Diagnostics/Heartbeat";
                    break;
                case "2":
                    context.Request.Path = "/Diagnostics/Deadbeat";
                    break;
            }

            await _next(context);
        }
    }
}

What am I doing wrong here?

To summarize my expectations:

  • With no custom header
    • User calls the uri https://myapplication.com/Diagnostics/Heartbeat
    • Application routes the request to the Heartbeat action of the Diagnostics controller
  • With the custom header having a value of "2"
    • User calls the uri https://myapplication.com/Diagnostics/Heartbeat
    • Application routes the request to the Deadbeat action of the Diagnostics controller

However, the actual behaviour is that when calling the above uri it is always the Heartbeat action that is called regardless of the presence or value of the custom header even though I can see that the value of context.Request.Path has been changed.


Solution

  • According to your description, you should add app.UseRouting(); before the app.MapControllers, then modifying the context.path could work.

    Like below :

    app.UseMiddleware<ModifyControllerMiddleware>();
    
    app.UseErrorHandler();
    
    app.UseAuthorization();
    
    //add this 
    app.UseRouting();
    
    app.MapControllers();
    
    app.Run();
    

    This is my middelware:

    public class ModifyControllerMiddleware
    {
        private readonly RequestDelegate _next;
    
        public ModifyControllerMiddleware(RequestDelegate next)
        {
            _next = next;
        }
    
        public async Task Invoke(HttpContext context)
        {
            switch (context.Request.Headers["x-intercept"])
            {
                case "1":
                    context.Request.Path = "/api/mydata";
                    break;
                case "2":
    
                    context.Request.Path = "/GetWeatherForecast";
                    //context.Request.Path = "/Diagnostics/Deadbeat";
                    break;
            }
    
            await _next(context);
        }
    }
    

    Result:

    enter image description here