Applying the defaults automatically

edit

Meziantou.AspNetCore.ServiceDefaults.AutoRegister is a source generator. Install it next to Meziantou.AspNetCore.ServiceDefaults, and every WebApplicationBuilder.Build() call of the project also applies the service defaults:

dotnet package add Meziantou.AspNetCore.ServiceDefaults
dotnet package add Meziantou.AspNetCore.ServiceDefaults.AutoRegister
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build(); // Also calls UseMeziantouConventions and MapMeziantouDefaultEndpoints

app.MapGet("/", () => "Hello World!");

The application has its health checks, OpenAPI document and security middleware without a call to UseMeziantouConventions or MapMeziantouDefaultEndpoints.

How it works

The generator uses C# interceptors: it replaces each WebApplicationBuilder.Build() call of the project with code that

  1. calls TryUseMeziantouConventions() on the builder,
  2. calls Build(),
  3. calls MapMeziantouDefaultEndpoints() on the application, and returns it.

Because MapMeziantouDefaultEndpoints runs right after Build(), its middleware come before everything you add to the application. The package enables the interceptors it needs in the project; there is nothing to configure.

The generator does nothing when the project does not reference Meziantou.AspNetCore.ServiceDefaults. It only intercepts WebApplicationBuilder.Build(): a host built with Host.CreateApplicationBuilder is not changed.

Configuring the defaults

Call UseMeziantouConventions with your options before Build(). The generated code calls TryUseMeziantouConventions, which does nothing when the conventions are already registered, so your options are kept:

var builder = WebApplication.CreateBuilder(args);
builder.UseMeziantouConventions(options => options.OpenApi.Enabled = false);

var app = builder.Build(); // Keeps these options: the generated code only adds the conventions when they are missing

Calling MapMeziantouDefaultEndpoints yourself after Build() is harmless: the second call does nothing. It does not move the middleware, though: they are already added by the generated code.

See Options for the available options.