Skip to content

Module .csproj references *.Contracts but injects services from impl assembly, causing opaque DI failures #129

@antosubash

Description

@antosubash

Several modules declare ProjectReference to peer modules' *.Contracts projects only, but their endpoints inject services implemented in the peer's main assembly. When a downstream app installs the module without the peer's runtime package, startup fails with a misleading error.

Concrete failures (consuming 0.0.34 from a fresh Microsoft.NET.Sdk.Web host)

Admin → OpenIddict. SimpleModule.Admin.csproj references SimpleModule.OpenIddict.Contracts only, but Endpoints/Admin/AdminSessionsEndpoint.cs injects IOpenIddictSessionContracts (implementation lives in SimpleModule.OpenIddict). Without the OpenIddict package installed, host crashes at startup with:

System.InvalidOperationException: Body was inferred but the method does not allow inferred body parameters.
Parameter           | Source
---------------------------------
id                  | Route (Inferred)
tokenId             | Route (Inferred)
sessionContracts    | Body (Inferred)

Minimal-API misclassifies the unresolved DI parameter as body-bound. The actual problem (missing service registration) is invisible.

Email → BackgroundJobs. SimpleModule.Email requires IBackgroundJobs from SimpleModule.BackgroundJobs for EmailService and RetryFailedEmailsJob but doesn't declare the dependency. Same opaque failure mode.

Fix

For each module that injects services from a peer at runtime, declare a PackageReference (not just *.Contracts) so NuGet pulls the impl transitively. Alternatively, add a startup validator (see related issue) that emits "ModuleX requires ModuleY to be installed" before the DI container is built.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions