Blaztrap.Aspire.Hosting.HttpEcho 0.3.0

dotnet add package Blaztrap.Aspire.Hosting.HttpEcho --version 0.3.0
                    
NuGet\Install-Package Blaztrap.Aspire.Hosting.HttpEcho -Version 0.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Blaztrap.Aspire.Hosting.HttpEcho" Version="0.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Blaztrap.Aspire.Hosting.HttpEcho" Version="0.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Blaztrap.Aspire.Hosting.HttpEcho" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Blaztrap.Aspire.Hosting.HttpEcho --version 0.3.0
                    
#r "nuget: Blaztrap.Aspire.Hosting.HttpEcho, 0.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Blaztrap.Aspire.Hosting.HttpEcho@0.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Blaztrap.Aspire.Hosting.HttpEcho&version=0.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Blaztrap.Aspire.Hosting.HttpEcho&version=0.3.0
                    
Install as a Cake Tool

Blaztrap.Aspire.Hosting.HttpEcho

In-process, Docker-free HTTP stub server for .NET 10 + Aspire. A WireMock-equivalent that ships as a single NuGet package and plugs straight into any Aspire AppHost via a clean builder.AddHttpEcho("echo") call site — no Projects.X metadata reference, no separate runner project.

The same assembly carries:

  • the stub server (an ASP.NET Core app the AppHost relaunches via dotnet <ownDll>),
  • the AppHost integration (AddHttpEcho, WithStub, WithHttpEchoEnvironment),
  • declarative validations (RequireJsonField, RequireJsonNumberRange, RequireHeader, RequireQuery),
  • code-based stubs via the HttpStubBase class for cases that outgrow declarative rules.

Install

dotnet add package Blaztrap.Aspire.Hosting.HttpEcho

Targets net10.0. Requires Aspire.Hosting 13.2+ on the AppHost side.

Quick start

In your Aspire AppHost project:

using Blaztrap.Aspire.Hosting.HttpEcho;

var builder = DistributedApplication.CreateBuilder(args);

var echo = builder.AddHttpEcho("echo")
    .WithStub(s => s.OnGet("/hello").RespondWith(200, "Hello"))
    .WithStub(s => s.OnGet("/json")
                    .RespondWith(200,
                        body: """{"message":"hi"}""",
                        headers: new() { ["Content-Type"] = "application/json" }))
    .WithStub(s => s.OnPost("/orders").RespondWith(202))
    .WithStub(s => s.OnPathMatching("^/users/[0-9]+$").RespondWith(200, "user-found"))
    .WithStub(s => s.OnGet("/slow").WithFixedDelay(TimeSpan.FromMilliseconds(750))
                                    .RespondWith(200, "ok"))
    .WithStub("DELETE", "/items/42", 204);

builder.AddProject<Projects.MyApp>("api")
    .WithHttpEchoEnvironment(echo)   // injects HttpEcho__BaseUrl
    .WaitFor(echo);

await builder.Build().RunAsync();

The consumer reads its endpoint from HttpEcho__BaseUrl (or HttpEcho:BaseUrl via IConfiguration) and points an HttpClient at it — same shape as any other Aspire resource.

Declarative validations

Stubs match by method / path / query / headers / body-regex like WireMock. Once matched, any declared validation runs against the request — the first failure short-circuits with its own status + body, simulating an API that rejects malformed input.

// POST /people — must carry valid email and phone; otherwise 400.
.WithStub(s => s.OnPost("/people")
    .RequireJsonField("email", @"^[^@\s]+@[^@\s]+\.[^@\s]+$",
        onFailBody: """{"error":"invalid email"}""")
    .RequireJsonField("phone", @"^\+?[0-9]{8,15}$",
        onFailBody: """{"error":"invalid phone"}""")
    .RespondWith(201, body: """{"id":"person-123"}"""))

// POST /transactions — body.amount must be a number in (0, 10_000].
.WithStub(s => s.OnPost("/transactions")
    .RequireJsonNumberRange("amount", min: 0.01m, max: 10_000m,
        onFailBody: """{"error":"amount out of allowed range"}""")
    .RespondWith(200, body: """{"status":"accepted"}"""))

Other built-in helpers:

Method Source Notes
RequireJsonField(selector, pattern?, ...) JSON body, dotted path required + optional regex
RequireJsonNumberRange(selector, min?, max?, ...) JSON body, dotted path numeric range
RequireHeader(name, pattern?, ...) request header required + optional regex
RequireQuery(name, pattern?, ...) query parameter required + optional regex
WithValidation(v => …) full control of HttpEchoStubValidation for anything the helpers don't cover

Code-based stubs

When a declarative rule won't cut it, derive from HttpStubBase. Un-overridden verbs answer 405 Method Not Allowed automatically.

public sealed class InventoryStub : HttpStubBase
{
    public override Task OnGet(HttpContext ctx, CancellationToken ct)
        => WriteJsonAsync(ctx, 200, """{"sku":"widget","stock":42}""", ct);

    public override Task OnDelete(HttpContext ctx, CancellationToken ct)
        => WriteTextAsync(ctx, 204, body: null, ct);

    // OnPost / OnPut / OnPatch → 405 by default
}

// AppHost:
.WithStub<InventoryStub>("/inventory/widget");

Constraints:

  • The class must have a public parameterless constructor — the stub server constructs its own instance via Activator.CreateInstance (the server runs in a separate process; an instance passed at AppHost time would never cross the boundary).
  • The class must live in an assembly that lands in the AppHost's bin directory (any project the AppHost references satisfies this — the AppHost's own assembly works too).

Admin endpoints

The stub server exposes two diagnostic endpoints (no authentication):

  • GET /__admin/health200 OK plain-text liveness probe.
  • GET /__admin/mappings → JSON dump of every configured stub + code stub, including validations attached to each.

How it works

The AppHost projects each stub as HttpEcho__Stubs__i__* environment variables (and HttpEcho__CodeStubs__i__* for code stubs). The stub server reads them via Microsoft.Extensions.Options. The library then relaunches itself as an Aspire ExecutableResource via dotnet <ownDll> — so the AppHost call site never has to know that the stub server is a project at all.

For NuGet consumers the package ships a .targets file that copies the lib's runtimeconfig.json + deps.json next to your consumer's binary so the relaunch works out of the box.

License & repository

See https://github.com/byteaid/blaztrap for source, issues, and changelog.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.3.0 55 7/13/2026