0

Edit:

The problem was that app.UseRouting(); was called before app.Use(async (context, next) => {...}). Once I place everything in this order, it worked:

app.Use(async (context, next) { ... });
app.UseRouting();
app.MapControllers();

Original Post:

I'm running a .net 8.0 asp.net minimal API app that is being deployed in various locations, each with different preceding request URL. For instance my search controller:

[ApiController]
[Route("[controller]")]
public class SearchController : ControllerBase {
    [HttpGet] public async Task<ActionResult<SomeValue[]>> Search([FromQuery] string query) { ... }
}

Can be triggered with any of these exemplary strings:

  1. /search?query=term
  2. /api/search?query=term
  3. /some/multi/part/prefix/search?query=term

I tried to find a way to consider only the last part, like [Route([*/controller])], but there's no way to accomplish it using the Route attribute, unfortunately.

So I tried to do some dynamic request manipulations, such as:

app.Use(async (context, next) => {
    context.Request.Path = "/search";
    var request = context.Request.Path.Value;
    var i = request.LastIndexOf('/');
    context.Request.Path = request[..i];
    await next();
});

But albeit witnessing the context.Request.Path indeed changing, the routing itself didn't seem to be affected by it.

So I tried app.MapDynamicControllerRoute<Router>("{**path}") and forced (for the sake of testing):

public class Router : DynamicRouteValueTransformer {
    public override ValueTask<RouteValueDictionary> TransformAsync(HttpContext httpContext, RouteValueDictionary values) {
        httpContext.Request.Path = "/search";
        values["path"] = "search";
        return new(values);
    }
}

And again: httpContext.Request.Path and values["path"] did both reflect the change, but the actual routing hasn't changed, and the controller hasn't been hit.

So what am I missing? any way to accomplish this dynamic routing?

I found no exact match for my case with actual working solution, and couldn't make app.MapDynamicControllerRoute<Router>("{**path}") change actual routing.

2
  • Can you please provide a full minimal reproducible example to play with? Commented Aug 22, 2024 at 22:58
  • "I'm running a .net 8.0 asp.net minimal API " - also it should be noted that minimal APIs do not use controllers. Commented Aug 22, 2024 at 22:59

1 Answer 1

0

You could try explicit add app.UseRouting(); after the middleware.

var app = builder.Build();
app.Use(async (context, next) => {
   //if the path contains "search", then change it all to "search"
    if (context.Request.Path.Value.Contains("/search"))
    {
        context.Request.Path = "/search";
    } 
    await next();
});
app.UseRouting();
...

From my experience, if you don't use "app.useRouting()" . Asp.net core will automatically use it at the beginning of middleware pipeline. But when you manually use it, you are forcing a pipeline order to use it.
enter image description here

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.