0

I have some plugin's which are basically input and output type definitions. I have a generic controller which i can add to the mvc pipeline. All works fine.

but I'm having trouble setting the api version on this generic controller. I know you can set this based upon an attribute on top of the controller class. But since you can't have this dynamic (attribute) don't allow it, i have no way to set the version for each instance of the generic controller.

Currently i just compile the controller for each instance on runtime and register i using the roslyn compiler.

is there a way to set the api-version somewhere in the pipeline of registering controllers in the mvc pipeline and endup with different api versions endpoints.

Frans
  • 131
  • 1
  • 10

1 Answers1

1

This can be achieved by using the Conventions API. It was designed to support this exact type of scenario:

https://github.com/microsoft/aspnet-api-versioning/wiki/API-Version-Conventions

This will only work on closed-generics, but it shouldn't be too much work to make that happen. Here's a couple of basic examples:

// typed, closed generic
options.Conventions.Controller<GenericController<PlugIn1>>().HasApiVersion(1,0);

// untyped, closed generic
var controllerType = typeof(GenericController<>).MakeGenericType(new []{typeof(PlugIn1)});
options.Conventions.Controller(controllerType).HasApiVersion(1,0);

You can also author your own custom conventions a la IControllerConvention. This approach could be used to version all controllers that inherit from GenericController<>. Then you just need to add it to the conventions like this:

options.Conventions.Add(new PlugInControllerConvention());

Hopefully that's enough to get you started. Feel free to ask more questions.

Chris Martinez
  • 3,185
  • 12
  • 28
  • ok thanks for the reply. I have looked at the documentation. it could be feasible on startup. with a little tweak --> .HasApiVersion(**new ApiVersion(1,0)**); but since i don't load the plugins on startup i wonder if this approach is going to work for me. I am wondering if i should use the IServiceCollection services in the feature provider. this is what i use in the feature PluginProvider : IApplicationFeatureProvider) ==== Feature.Controllers.Add(controllerPluginType.MakeGenericType(inputType).GetTypeInfo()); ==== can i add the ApiVersion at this point? – Frans Jul 01 '19 at 09:04
  • That should be technically possible, but you're probably going to have to build up the conventions and apply them later yourself. By default, the API version conventions are applied via a custom **IApplicationModelProvider**. The controllers don't have to be _loaded_, but their types do have to known. If you're delaying that, you'd need to apply the conventions once you discover them. If plug-in controllers, their routes, and their API versions do not overlap with other controllers, then this should be fine; otherwise, the API versions sets would not be properly aggregated. – Chris Martinez Jul 01 '19 at 14:51
  • I'm not sure exactly when or how you're loading your controllers, but a reasonable time to apply the conditions is via a custom **IActionDescriptorChangeProvider** service. You can get to the existing conventions by injecting `IOptions` into your service or you can imperatively create a new instance a la `new ApiVersionConventionBuilder()` and then applying the conventions to each controller type. That should get you started. – Chris Martinez Jul 01 '19 at 15:00