0

I'm working on an ASP.NET Core application where I have a default route template, for example: ~/api/{area}/[controller]/{action?}/{id?}.

My goal is to match incoming URLs with other route templates and dynamically reconstruct them with the default route template when no direct match is found.

Consider a scenario where someone sends a request like ~/{area}/api/[controller]/{action?}/{id?}. The first call to app.UseRouting(), EndpointRoutingMiddleware doesn't find any match.

In such cases, I want to rebuild the path dynamically to match my default route template (~/api/{area}/[controller]/{action?}/{id?}) and then trigger app.UseRouting() again to find the correct endpoint.

Startup.cs;

app.UseRouting();

app.UseMiddleware<RoutingMatcherMiddleware>();

app.UseRouting();

Middleware;

public Task Invoke(HttpContext context)
{
    var endpointFeature = context.Features[typeof(IEndpointFeature)] as IEndpointFeature;
    var endpoint = endpointFeature?.Endpoint;

    if (endpoint != null)
    {
        return _next(context);
    }

    //My other route templates that I didn't define on my BaseApiController
    foreach (var routeTemplate in _routeTemplates)
    {
        var templateParser = TemplateParser.Parse(routeTemplate);
        var matcher = new TemplateMatcher(templateParser, null);
        var values = new RouteValueDictionary();
        if (matcher.TryMatch(context.Request.Path, values))
        {
            context.Request.Path = ReBuildRequestPath(context.Request.Path, values);
            break;
        }
    }

    return _next(context);
}

But this logic doesn't work properly since the second UseRouting overrides the request pipeline and the first one is completely ignored. And situation causes that endpoint is always null here;

if (endpoint != null)
{
    return _next(context);
}

In sum, my custom matcher is executed for every request regardless it is matched with my default template or not.

Same problem mentioned here as well;

https://github.com/dotnet/aspnetcore/issues/17210

Any idea about alternative solutions/ideas ?

Note: I am restricted to define all possible route templates on my BaseApiController due to performance issue on .NET 5 and this is why I am looking for a dynamic solution;

https://github.com/dotnet/aspnetcore/issues/30092

3
  • How about using UseWhen or MapWhen ? Commented Dec 18, 2023 at 10:20
  • I also tried UseWhen but unfortunetely, it doesn't work since Routing middleware is terminal middleware, this is from official documentation; "...branches the request pipeline based on the result of the given predicate. Unlike with MapWhen, this branch is rejoined to the main pipeline if it doesn't short-circuit or contain a terminal middleware" Commented Dec 18, 2023 at 12:12
  • It's a different issue. How about using 2 attributes above the Controller? Commented Dec 19, 2023 at 8:23

0

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.