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:
/search?query=term/api/search?query=term/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.
