From 26190c13489886be91ecfe6deaf41ccb70055435 Mon Sep 17 00:00:00 2001 From: Mauro Servienti Date: Thu, 5 Mar 2026 20:50:05 +0100 Subject: [PATCH] Document web app project structure, port, and container log gotchas Adds a 'Project structure and Dockerfile' sub-section to the web app hosting section covering: - WebApp.Testing must use Sdk="Microsoft.NET.Sdk.Web" or wwwroot content items are excluded from the publish output (symptom: StaticFileMiddleware warning in container logs) - ReferenceOutputAssembly="false" on the production project reference also suppresses content items - launchSettings.json is ignored in containers; default port is 8080 - Razor views are pre-compiled in Release; .cshtml files absent is expected - DataProtection and libgssapi_krb5 warnings are harmless in test containers Co-Authored-By: Claude Sonnet 4.6 --- docs/getting-started.md | 48 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/docs/getting-started.md b/docs/getting-started.md index 3617a28..32ffae4 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1021,6 +1021,54 @@ Assert.That(results.HandlerInvoked("OrderCreatedHandler").EndpointName, Is.Equal `GetBaseUrl(8080)` resolves the host-mapped port assigned to container port 8080 at runtime. +#### Project structure and Dockerfile + +The companion project must use `Sdk="Microsoft.NET.Sdk.Web"`. Using the plain `Sdk="Microsoft.NET.Sdk"` (the default for console apps) means web content items — including `wwwroot` — are not included in the publish output. The symptom is a warning in the container logs: + +``` +warn: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[16] + The WebRootPath was not found: /app/wwwroot. Static files may be unavailable. +``` + +```xml + + + ... + + +``` + +Also ensure the reference to the production project does **not** have `ReferenceOutputAssembly="false"` — that attribute suppresses content items as well as the DLL. The `ReferenceOutputAssembly="false"` pattern is only correct for `WebApp.Tests` → `WebApp.Testing` (the NUnit/xUnit project that never builds the image). + +**Port**: `launchSettings.json` is ignored inside Docker containers. The ASP.NET Core base images default to port **8080** on .NET 8 and later. Declare the binding when registering the endpoint and use it in the test: + +```csharp +.AddEndpoint("WebApp", "WebApp.Testing/Dockerfile", + containerBuilder: b => b.WithPortBinding(8080, assignRandomHostPort: true)) +``` + +**Views**: Razor views are pre-compiled into the assembly during `dotnet publish -c Release` (the default). The `.cshtml` files will not appear in the publish output — this is expected and the views will render correctly. Static files in `wwwroot` are copied to the publish output automatically and served from `/app/wwwroot` inside the container. + +**Container log noise**: two warnings appear in all ASP.NET Core containers and are harmless in test environments: + +- _DataProtection keys stored in `/root/.aspnet/DataProtection-Keys`_ — keys won't survive a container restart, which doesn't matter for tests. +- _Cannot load library `libgssapi_krb5.so.2`_ — .NET probes for Kerberos on startup; the slim `aspnet` base image doesn't include it. Safe to ignore unless you are using Windows/Negotiate authentication. + +A minimal Dockerfile for a web app companion project: + +```dockerfile +FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build +WORKDIR /src +COPY . . +RUN dotnet restore WebApp.Testing/WebApp.Testing.csproj +RUN dotnet publish WebApp.Testing/WebApp.Testing.csproj -c Release -o /app/publish + +FROM mcr.microsoft.com/dotnet/aspnet:10.0 +WORKDIR /app +COPY --from=build /app/publish . +ENTRYPOINT ["dotnet", "WebApp.Testing.dll"] +``` + ## Complete example The following end-to-end example mirrors the sample included with this repository. It shows two endpoints, a saga with a timeout, a failure scenario, and WireMock stubbing.