MartinDrozdik.DDD.Web
0.5.3
See the version list below for details.
dotnet add package MartinDrozdik.DDD.Web --version 0.5.3
NuGet\Install-Package MartinDrozdik.DDD.Web -Version 0.5.3
<PackageReference Include="MartinDrozdik.DDD.Web" Version="0.5.3" />
<PackageVersion Include="MartinDrozdik.DDD.Web" Version="0.5.3" />
<PackageReference Include="MartinDrozdik.DDD.Web" />
paket add MartinDrozdik.DDD.Web --version 0.5.3
#r "nuget: MartinDrozdik.DDD.Web, 0.5.3"
#:package MartinDrozdik.DDD.Web@0.5.3
#addin nuget:?package=MartinDrozdik.DDD.Web&version=0.5.3
#tool nuget:?package=MartinDrozdik.DDD.Web&version=0.5.3
DDD for ASP.NET Core - Web Plumbing That Doesn't Suck
Opinionated web infrastructure for .NET based on MartinDrozdik.DDD. Includes error handling, logging, telemetry, health checks, and other setup you'll need anyway. Check the demo.
Installation
dotnet add package MartinDrozdik.DDD.Web
Philosophy
Same as the core DDD library.
This package provides basic scaffolding for ASP.NET apps while staying out of your way when you need to do your thing. Everything is optional, but it's tested together.
iT jUsT wOrKs
Quick Start
Bare minimum setup - one liner to get logging, error handling, OpenAPI, health checks, telemetry, and HTTP resilience:
var builder = WebApplication.CreateBuilder(args);
builder.AddAppServices(); // the magic one liner
// ...
var app = builder.Build();
app.UseAppMiddlewares(); // the other magic one liner
// ...
await app.RunAsync();
Done. You've got a production-ready baseline. Now go build your actual features.
You want to use Apire? We got you fam! The OTEL works with Apire out of the box.
All-in-One Setup
The AddAppServices() extension registers:
- Logging - Structured logging that actually helps you debug but doesn't leak sensitive info in production
- Error Handling - Converts your DDD exceptions to proper HTTP RFC7807 error responses
- OpenAPI - Auto-generated API docs (because manually writing swagger is hell)
- Health Checks - basic
/health,/health/liveand/health/readyendpoints - OpenTelemetry - Metrics, traces, and logs (exports to OTLP when configured via OTEL environment variables)
- HTTP Resilience - Default policies for HTTP clients
- Static file path provider - Because you probably need to serve some static files at some point
Don't want all of it? Use the individual extensions instead. I won't judge.
Or just turn them off via settings:
var options = MartinDrozdik.DDD.Web.WebApplicationOptions.Default with
{
UseStaticFilePathProvider = false,
};
builder.AddAppServices(options);
Modules
What goodies do you want to use? Just call the appropriate extension method:
Options
Leverages IOptions<T> with FluentValidation for configuration validation and automatic binding.
Configured to fail fast if your configuration is invalid. No more "wOrKs On My MaChInE".
public class InvoiceOptions : IValidatedAppOptions<InvoiceOptions>
{
public static string Section => "App:Invoice"; // Simple binding from config (appsettings etc.)
// FluentValidation validator, because attributes are for suckers
public static AbstractValidator<InvoiceOptions> Validator { get; } = new OptionsValidator();
// Your actual options properties:
public required int StartingId { get; init; }
public required string DefaultName { get; init; }
private class OptionsValidator : AbstractValidator<InvoiceOptions>
{
public OptionsValidator()
{
RuleFor(e => e.StartingId).GreaterThanOrEqualTo(0);
RuleFor(e => e.DefaultName).NotNull().NotEmpty();
}
}
}
// Register it:
builder.Services.AddValidatedAppOptions<InvoiceOptions>();
For simpler options without validation:
public class SimpleOptions : IAppOptions
{
public static string Section => "App:Simple";
public required string Value { get; init; }
}
builder.Services.AddAppOptions<SimpleOptions>();
EEE (Ezy Error Ehndling)
Automatic conversion of DDD exceptions to HTTP responses:
BusinessRuleValidationException→ 400 Bad RequestValidationException(FluentValidation) → 400 Bad RequestBusinessRuleException→ 500 Internal Server Error (with business details)- Anything else → 500 Internal Server Error
In development, you get detailed info. In production, you get clean and safe error messages. The middleware handles it:
builder.Services.AddAppErrorHandling();
//...
app.UseExceptionHandler();
Your domain layer throws exceptions. The middleware translates them. You don't touch HTTP in your business logic.
Database Setup
There is 99 % chance you are using EF core with relational database.
We got you, just use the extension method:
// appsettings.json
{
"App": {
"Database": {
"ConnectionString": "Data Source=app.db"
}
}
}
// With DatabaseOptions from config:
builder.AddAppDbContext<YourDbContext>((options, dbBuilder) =>
{
dbBuilder.UseSqlite(options.ConnectionString);
// Use SQL Server, PostgreSQL, MySQL, whatever you like.
});
// Or manual configuration:
builder.AddAppDbContext<YourDbContext>(dbBuilder =>
{
dbBuilder.UseSqlServer(connectionString);
});
- In development: sensitive data logging and detailed errors.
- In production: none of that.
Ensure your database exists:
await app.EnsureCreatedDatabaseAsync<YourDbContext>();
Or for you migration folks:
await app.MigrateDatabaseAsync<YourDbContext>();
Health Checks
The most basic liveness and readiness probes. Because Kubernetes will ask:
builder.AddAppHealthChecks();
// Or add custom checks:
builder.AddAppHealthChecks(checks =>
{
// Add more checks as needed
});
app.MapAppHealthChecks(); // Registers /health/live and /health/ready
Timeouts are configured. Todd says "it just works".
Mediator
Automatic request/response logging for your CQRS handlers:
builder.Services.AddMediator(config =>
{
var integration = new LoggingPipelineIntegrator()
.Merge<ValidationPipelineIntegrator>();
config.WithCommand<CreateInvoiceCommand, InvoiceId, CreateInvoiceCommandHandler>(integration);
});
Every command and query gets logged with info.
Telemetry (OpenTelemetry)
Traces, metrics, and logs for ASP.NET Core and HTTP clients:
builder.AddAppOpenTelemetry();
Configure export via environment variables:
OTEL_EXPORTER_OTLP_ENDPOINT=http://your-collector:4317
OTEL_SERVICE_NAME=your-service
OTEL_SERVICE_VERSION=1.0.0
Check the docs with full list of OTEL environment variables.
Health check requests are filtered out of traces because who cares about those.
Reverse Proxy Support
One liner for handling proxied requests (nginx, YARP etc.):
app.IsBehindProxy();
Handles X-Forwarded-* headers.
HTTP Client Resilience
builder.Services.AddHttpClientResilience();
Because the network is unreliable and you know it.
Static File Path Provider
How much time did you spend solving an issue solved by clearing browser cache? Yeah, me too. This path modification with query string versioning is the most basic solution to this problem.
IStaticFilePathProvider provider; // inject it where you need it
provider.PathTo("file.js");
Returns a version depending on the environment:
- Development: returns
"file.js?version={unix-timestamp}"to bust cache on every request. - Production: returns
"file.js?version=1.2.3"depending on your appsettings. Bust cache when you deploy a new version, but not on every request.
// appsettings.json
{
"App": {
"StaticFileVersioning": {
"Version": "1.2.3"
}
}
}
Demo App
Check out the demo project for examples.
It's structured for demo purposes, I would recommend structuring with vertical slices in a real app, but it shows all the features in one place.
It's a simple ASP.NET Core app with a few endpoints, using the mediator for commands and queries, and demonstrating the error handling and telemetry in action. Check it out for examples of how to use the library in a real app...
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- FluentValidation (>= 12.1.1)
- MartinDrozdik.DDD (>= 0.5.3)
- Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore (>= 10.0.6)
- Microsoft.AspNetCore.OpenApi (>= 10.0.6)
- Microsoft.EntityFrameworkCore (>= 10.0.6)
- Microsoft.Extensions.Http.Resilience (>= 10.5.0)
- OpenTelemetry.Exporter.OpenTelemetryProtocol (>= 1.15.2)
- OpenTelemetry.Extensions.Hosting (>= 1.15.2)
- OpenTelemetry.Instrumentation.AspNetCore (>= 1.15.1)
- OpenTelemetry.Instrumentation.Http (>= 1.15.0)
- OpenTelemetry.Instrumentation.Runtime (>= 1.15.0)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on MartinDrozdik.DDD.Web:
| Package | Downloads |
|---|---|
|
MartinDrozdik.DDD.Testing
A library to support testing of websites using the MartinDrozdik.DDD packages. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.7.0 | 273 | 5/16/2026 |
| 0.6.0 | 142 | 5/2/2026 |
| 0.5.3 | 173 | 4/19/2026 |
| 0.5.2 | 118 | 4/18/2026 |
| 0.5.1 | 128 | 4/10/2026 |
| 0.5.0 | 144 | 4/6/2026 |
| 0.4.4 | 122 | 4/6/2026 |
| 0.4.2 | 113 | 4/6/2026 |
| 0.4.1 | 134 | 4/6/2026 |
| 0.1.4 | 159 | 3/21/2026 |
| 0.1.3 | 175 | 2/14/2026 |
| 0.1.2 | 108 | 2/13/2026 |
| 0.1.1 | 113 | 2/13/2026 |
| 0.1.0 | 116 | 2/9/2026 |