MinimalWebAPI.md
May 9, 2026 ยท View on GitHub
Minimal Web API
This example shows how to build a Minimal Web API with Pure.DI, using generated roots for the application entry point while still allowing ASP.NET Core endpoint handlers to request services from Microsoft dependency injection.
Tip
Owned<Program> is used as the application root so disposable dependencies created for that root are released deterministically. Endpoint handlers may still use [FromServices] for services supplied by ASP.NET Core.
The composition setup file is Composition.cs:
using Pure.DI;
using Pure.DI.MS;
using static Pure.DI.Lifetime;
namespace MinimalWebAPI;
partial class Composition : ServiceProviderFactory<Composition>
{
// IMPORTANT:
// Only composition roots (regular or anonymous) can be resolved through the `IServiceProvider` interface.
// These roots must be registered using `Root<>(...)` or `RootBind<>()` calls.
[System.Diagnostics.Conditional("DI")]
private void Setup() => DI.Setup()
// Owned is used here to dispose of all disposable instances associated with the root.
.Root<Owned<Program>>(nameof(Root))
.Root<IClockViewModel>()
.Bind().To<ClockViewModel>()
.Bind().To<ClockModel>()
.Bind().As(Singleton).To<Ticks>()
// Infrastructure
.Bind().To<MicrosoftLoggerAdapter<TT>>()
.Bind().To<CurrentThreadDispatcher>();
}
The composition class inherits from ServiceProviderFactory<T>, where T is the composition class itself. Only registered roots can be resolved through the Microsoft IServiceProvider; this sample also resolves the Owned<Program> root directly from the composition.
The web application entry point is in the Program.cs file:
using MinimalWebAPI;
using var composition = new Composition();
var builder = WebApplication.CreateBuilder(args);
// Uses Composition as an alternative IServiceProviderFactory
builder.Host.UseServiceProviderFactory(composition);
var app = builder.Build();
// Creates an application composition root of type `Owned<Program>`
using var root = composition.Root;
root.Value.Run(app);
partial class Program(
IClockViewModel clock,
IAppViewModel appModel)
{
private void Run(WebApplication app)
{
app.MapGet("/", (
// Dependencies can be injected here as well
[FromServices] ILogger<Program> logger) => {
logger.LogInformation("Start of request execution");
return new ClockResult(appModel.Title, clock.Date, clock.Time);
});
app.Run();
}
}
The project file looks like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<ItemGroup>
<PackageReference Include="Pure.DI" Version="2.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pure.DI.MS" Version="2.4.0" />
</ItemGroup>
</Project>
It contains additional references to NuGet packages:
| Pure.DI | DI source code generator | |
| Pure.DI.MS | Add-ons for Pure.DI to work with Microsoft DI |