TCIS.Pluggable.Engine.AspNetCore 1.0.0-rc.16

This is a prerelease version of TCIS.Pluggable.Engine.AspNetCore.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package TCIS.Pluggable.Engine.AspNetCore --version 1.0.0-rc.16
                    
NuGet\Install-Package TCIS.Pluggable.Engine.AspNetCore -Version 1.0.0-rc.16
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="TCIS.Pluggable.Engine.AspNetCore" Version="1.0.0-rc.16" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="TCIS.Pluggable.Engine.AspNetCore" Version="1.0.0-rc.16" />
                    
Directory.Packages.props
<PackageReference Include="TCIS.Pluggable.Engine.AspNetCore" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add TCIS.Pluggable.Engine.AspNetCore --version 1.0.0-rc.16
                    
#r "nuget: TCIS.Pluggable.Engine.AspNetCore, 1.0.0-rc.16"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package TCIS.Pluggable.Engine.AspNetCore@1.0.0-rc.16
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=TCIS.Pluggable.Engine.AspNetCore&version=1.0.0-rc.16&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=TCIS.Pluggable.Engine.AspNetCore&version=1.0.0-rc.16&prerelease
                    
Install as a Cake Tool

TCIS.Pluggable.Engine.AspNetCore

Lets a plugin expose its own HTTP endpoints — Minimal APIs, gRPC services or SignalR hubs — without the Platform host knowing they exist.

Split out of TCIS.Pluggable.Engine on purpose: a Worker Service, a console app or a Hangfire host can use the pipeline engine without dragging in the whole of ASP.NET Core.


Table of contents

Section Contents
1 Registration
2 Exposing endpoints from a plugin
3 How mapping works
4 Routing conventions
5 Pitfalls

1. Registration

dotnet add package TCIS.Pluggable.Engine.AspNetCore
var app = builder.Build();

app.UseTCISCore();
app.UseRequestTimeouts();

app.MapControllers();
app.MapPluggableEndpoints();   // <- maps endpoints declared by loaded modules

app.Run();

The namespace stays TCIS.Pluggable.Engine.Modules even though the types now live in a separate assembly — existing code only needs to add the package reference, not touch its using directives.


2. Exposing endpoints from a plugin

Implement IPluggableEndpointModule — it extends ISiteModule, so one class both registers services and maps routes:

public sealed class CatLaiModule : IPluggableEndpointModule
{
    public string SiteCode => "CATLAI";

    public void RegisterServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddScoped<ICustomsGateway, CatLaiCustomsGateway>();
    }

    public void MapEndpoints(IEndpointRouteBuilder endpoints)
    {
        var group = endpoints.MapGroup("/api/v1/sites/catlai")
                             .RequireAuthorization()
                             .WithTags("CatLai");

        group.MapPost("/customs/webhook", async (
            CustomsCallback payload,
            ICustomsGateway gateway,
            CancellationToken ct) =>
        {
            await gateway.HandleCallbackAsync(payload, ct);
            return Results.Accepted();
        });
    }
}

This is the sanctioned way to add a port-specific integration — a customs webhook, a partner callback, a scale-house feed — without touching the Platform routing table.


3. How mapping works

MapPluggableEndpoints() walks IModuleRegistry, and for every module that implements IPluggableEndpointModule it calls MapEndpoints during startup.

That means:

  • Only modules actually loaded for this host contribute endpoints. A plugin the host never passed to AddSitePlugins maps nothing.
  • Mapping happens once at startup, not per request. There is no routing cost at runtime.
  • A Platform module can implement the interface too, if the endpoint is genuinely standard business.

4. Routing conventions

Endpoints coming from plugins are still public API, so Chapter 1 applies in full. In particular:

Rule Meaning here
API-001 / API-002 Plural nouns, kebab-case paths
API-008 Version in the path — /api/v1/...
API-011 Wrap responses in the standard envelope
API-023 Deny by default — call RequireAuthorization() on the group

Prefix plugin routes with the site (/api/v1/sites/catlai/...) so two ports cannot collide on the same path when several small ports share one deployment. Nothing enforces this automatically; a collision would surface as an ambiguous-route exception at startup, which is loud but late.


5. Pitfalls

# Pitfall Consequence
1 Business logic inside MapEndpoints Same defect as a fat controller — untestable and unreachable from gRPC or a consumer. Delegate to a handler or pipeline
2 Forgetting RequireAuthorization() An open endpoint that no Platform review would ever see, because it lives in plugin code
3 Two plugins mapping the same route Ambiguous-route exception at startup — prefix by site to avoid it
4 Calling MapPluggableEndpoints() before authentication middleware Authorization metadata is present but never evaluated
5 Using this package in a Worker Service Unnecessary — the whole point of the split is that non-web hosts do not need it
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0-rc.19 35 8/13/2026
1.0.0-rc.18 31 8/13/2026
1.0.0-rc.17 30 8/13/2026
1.0.0-rc.16 40 8/13/2026
1.0.0-rc.15 41 8/12/2026
1.0.0-rc.14 42 8/12/2026
1.0.0-rc.13 41 8/11/2026
1.0.0-rc.12 50 8/10/2026