Asp.net core web api - extending attribute route generation

Viewed 322

Suppose I want to allow people to create plugins for my ASP.NET Core Web API application.

The plugins can include endpoints using attribute routing:

    [Route("[controller]")]
    public class SomePlugin: ControllerBase
    {

I can load these plugins and add AssemblyPart's to the Parts Manager in Asp.net core, and stuff will work - no problem so far.

However suppose two plugins both use the same route accidentally. There is a chance they might accidentally conflict with eachother - one plugin overriding the route of another. I don't want this.

So what I need to do is make sure that each plugin / assembly, is assigned it's own dedicated URL space that it's routes are relative within. Basically it's own dedicated Url base path / prefix.

So in the case of the above plugin, even though the developer has used a Route attribute of [Route("[controller]")] - i don't want that to be the final route. I want to make that relative to a prefix unique to that plugin - so the actual route I want generated would be [Route("{plugin-prefix}/[controller]")].

This policy should hopefully guarantee that plugins can't conflict with each other routes, accidentally.

So hopefully now that I have explained the problem, my question is, is there an appropriate way / mechanism to achieve this in asp.net core right now? I am using ASP.NET Core 3.0 with the new Endpoint Routing mechanism.

1 Answers

I have not tried it myself, but you should be able to achieve that via Custom routing convention. Something like this :

public class PrefixConvention : IApplicationModelConvention
{
    public void Apply(ApplicationModel application)
    {
        foreach (var controller in application.Controllers)
        {
            controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel()
            {
                Template = // "ADD_PREFIX_BASED_ON_CONTROLLER_TYPE"?
            };
        }
    }
}

And then add it to MVC conventions.

services.AddMvc(options =>
{
    options.Conventions.Add(new PrefixConvention ());
});
Related