Skip to content

Modules

A module is a class that registers services and, in web hosts, maps endpoints. Modules declare what they need with [DependsOn]; Coworkee loads the whole graph once, in dependency order.

[DependsOn(typeof(CoworkeeODataModule), typeof(CoworkeeStorageModule))]
public sealed class MyAppDocumentsModule : CoworkeeModule, IWebModule
{
    public override void ConfigureServices(ModuleServiceContext context)
    {
        context.Services.AddMessagingFromAssembly(typeof(MyAppDocumentsModule).Assembly);
        context.Services.AddODataEntity<Document>("Documents", DocumentPermissions.Documents.View, d => d.BlobKey);
    }

    public void ConfigureApplication(WebApplication app) => app.MapDocumentEndpoints();
}
Member When it runs
ConfigureServices(ModuleServiceContext) While the host builds its service collection. context.Configuration is the host configuration.
IWebModule.ConfigureApplication(WebApplication) After the app is built, in module order. Map endpoints, add middleware.

One root per host

A host names one root module, the rest follows from the dependencies:

builder.AddCoworkee<MyAppApiModule>();   // registers every module in the graph
var app = builder.Build();
app.UseCoworkee();                       // authentication, problem details, then each IWebModule

Hosts without HTTP, such as the migration service, call services.AddCoworkeeModules<TRoot>(configuration) instead.

Different hosts compose different graphs from the same modules. In the template the API root depends on the catalog and documents modules, the auth host only on infrastructure, CoworkeeAuthServerModule and, with samples, the slim MyAppRegistrationDocumentsModule that stores registration documents without the documents API. A module that is not in a host's graph costs that host nothing.

Contributors instead of central lists

Modules never edit a central list. They add contributors that the owning package collects:

Contributor Package Adds
IModelContributor Infrastructure entity mappings to the app's DbContext
IPermissionDefinitionContributor Application permission groups and names
ISettingDefinitionContributor Settings runtime settings with scope and type
IMailTemplateContributor Mailing mail templates with defaults per culture
INavigationContributor Client.Blazor menu entries
IAppBarContributor Client.Blazor components in the app bar

That is why a module can be added or removed without touching anything else.

Usings

Most code needs few namespaces:

using Coworkee.Core.Modularity;          // CoworkeeModule, DependsOn, ModuleServiceContext
using Coworkee.AspNetCore;               // IWebModule, AddCoworkee, UseCoworkee
using Coworkee.Application.Messaging;    // AddMessagingFromAssembly, IDispatcher, ICommand, IQuery, IHandler
using Coworkee.Core.Results;             // Result, Error

Packages and namespaces has the full list.