Web Hosting
ASP.NET applications often end up with a bloated Program.cs where every cross-cutting concern — authentication, CORS, Swagger, logging, health checks — is mixed together. Shiny Web Hosting lets you break that apart into modular IInfrastructureModule classes, each responsible for its own service registration and middleware configuration. Modules are discovered automatically, keeping your startup clean.
Features
Section titled “Features”- Modular
IInfrastructureModuleinterface — combines service registration and middleware configuration in one class - Automatic assembly scanning to discover and run all modules
- Explicit registration option for reflection-free, AOT-compatible setups
- Clean separation of concerns — one module per infrastructure component
-
Install the NuGet package:
Terminal window dotnet add package Shiny.Extensions.WebHosting -
Create infrastructure modules for each concern:
using Shiny.Extensions.WebHosting;public class SwaggerModule : IInfrastructureModule{public void Add(WebApplicationBuilder builder){builder.Services.AddEndpointsApiExplorer();builder.Services.AddSwaggerGen();}public void Use(WebApplication app){if (app.Environment.IsDevelopment()){app.UseSwagger();app.UseSwaggerUI();}}} -
Wire up modules in
Program.cs:var builder = WebApplication.CreateBuilder(args);builder.AddInfrastructure(Assembly.GetExecutingAssembly());var app = builder.Build();app.UseInfrastructure();app.Run();
Creating Modules
Section titled “Creating Modules”Each module implements IInfrastructureModule with two methods:
Add(WebApplicationBuilder builder)— register services, configuration, and anything that happens beforeBuild()Use(WebApplication app)— configure middleware, endpoints, and anything that happens afterBuild()
public class CorsModule : IInfrastructureModule{ public void Add(WebApplicationBuilder builder) { builder.Services.AddCors(options => { options.AddDefaultPolicy(policy => policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); }); }
public void Use(WebApplication app) { app.UseCors(); }}
public class AuthModule : IInfrastructureModule{ public void Add(WebApplicationBuilder builder) { builder.Services.AddAuthentication() .AddJwtBearer(); builder.Services.AddAuthorization(); }
public void Use(WebApplication app) { app.UseAuthentication(); app.UseAuthorization(); }}
public class HealthCheckModule : IInfrastructureModule{ public void Add(WebApplicationBuilder builder) { builder.Services.AddHealthChecks(); }
public void Use(WebApplication app) { app.MapHealthChecks("/health"); }}Registration Options
Section titled “Registration Options”Assembly Scanning
Section titled “Assembly Scanning”Automatically discovers all IInfrastructureModule implementations in the specified assemblies:
// Scan specific assembliesbuilder.AddInfrastructure(Assembly.GetExecutingAssembly());
// Scan all loaded assemblies in the AppDomainbuilder.AddInfrastructureForAppDomain();Explicit Registration
Section titled “Explicit Registration”For AOT-compatible setups or when you want full control over which modules run:
builder.AddInfrastructureModules( new SwaggerModule(), new CorsModule(), new AuthModule(), new HealthCheckModule());Clean Program.cs
Section titled “Clean Program.cs”The end result is a minimal Program.cs:
using System.Reflection;using Shiny.Extensions.WebHosting;
var builder = WebApplication.CreateBuilder(args);builder.AddInfrastructure(Assembly.GetExecutingAssembly());
var app = builder.Build();app.UseInfrastructure();
app.Run();All the complexity lives in focused, testable module classes instead of a single monolithic startup file.