VirtoCommerce/vc-platform

Tagging controllers from additional module assemblies

j-mok opened this issue · 0 comments

j-mok commented

Problem:
The current logic for controller action tagging in Swagger is to group actions by modules and tag the rest with Platform fallback:

private static IList<string> GroupByModuleName(this ApiDescription api, IServiceCollection services)
{
var providerSnapshot = services.BuildServiceProvider();
var moduleCatalog = providerSnapshot.GetRequiredService<ILocalModuleCatalog>();
// ------
// Lifted from ApiDescriptionExtensions
var actionDescriptor = api.GetProperty<ControllerActionDescriptor>();
if (actionDescriptor == null)
{
actionDescriptor = api.ActionDescriptor as ControllerActionDescriptor;
api.SetProperty(actionDescriptor);
}
// ------
var moduleAssembly = actionDescriptor?.ControllerTypeInfo.Assembly ?? Assembly.GetExecutingAssembly();
var groupName = moduleCatalog.Modules.FirstOrDefault(m => m.ModuleInstance != null && m.Assembly == moduleAssembly);
return new List<string> { groupName != null ? groupName.ModuleName : "Platform" };
}

The problem is that if some or all module controllers are not in the main module assembly (usually the Foo.Web) but in referenced assemblies, then they end up tagged with Platform. That clutters the Platform tag with non-platform controller actions and gives the impression that the module is missing its own actions.

Solution:
Allow additional assemblies to be enumerated in module manifest and then treated as module's own when grouping controller actions. This could look like this:

<module>
    <id>Foo</id>
    <!-- ... -->
    <api>
        <swagger>
            <additionalAssemblies>
                <include>Foo.Web.MoreControllers</include>
                <include>Foo.Web.EvenMoreControllers</include>
            </additionalAssemblies>
        </swagger>
    </api>
</module>

Some assumptions:

  • Assemblies are referenced using their simple names.
  • Entry validation skipped for simplicity.
  • It is the responsibility of module author to include appropriate assemblies, otherwise current behavior applies.
  • The root module assembly is not required to be included in the list (hence addtional) - it is always considered for per-module tagging.

Alternative:
Module assembly dependency graph can be crawled and all found assemblies could be considered for controller action tagging. The downsides are more complex implementation, possibly bigger resource usage and lack of fine control. The upside is that it would work automatically without the need to maintain the manifest.

Proposal of changes:
Implement module manifest extension as described above (or something similar) and modify action grouping accordingly.

Additional context:
It's probably not a frequent requirement, and small, focused modules will not benefit from it. Nonetheless there are sometimes overgrown modules split into multiple assemblies but deployed as a single module that have segregated controllers some of which incorrectly end up in the Platform tag.