Running on .NET 5.0 now results in "A valid non-empty content root must be provided"
See original GitHub issueDescribe the bug
Since upgrading to .NET 5.0, I have noticed that when deploying a product as a single file executable to Alpine Linux and running it under a rootless container via podman, I get the following error now. I really hope Kestrel does not require a directory for static content now, I use Kestrel for lightweight services and am quite happy with the 404 for any path not routed.
Unhandled exception. System.ArgumentException: A valid non-empty content root must be provided. (Parameter 'contentRootPath')
at Microsoft.AspNetCore.Hosting.Internal.HostingEnvironmentExtensions.Initialize(IHostingEnvironment hostingEnvironment, String contentRootPath, WebHostOptions options)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at NamespaceChanged.Program.RunAsync(Options options)
at CommandLine.ParserResultExtensions.WithParsedAsync[T](ParserResult`1 result, Func`2 action)
at NamespaceChanged.Program.Main(String[] args)
at NamespaceChanged.Program.<Main>(String[] args)
I should mention that I do not use ASP.NET Core beyond using the Kestrel web server. I use my routing library, Routable
and handle requests directly. Routable’s source is available here, but basically it does not do anything except add a handler for requests, check if the request path is matches a known route and handle it if it does, if not, it gives back control to Kestrel which until now would merrily issue a 404 (or hand off to the next handler).
The initialization looks like this:
using var server = new WebHostBuilder()
.UseKestrel(kestrelOptions => kestrelOptions.ListenAnyIP(options.HttpPort))
.Configure(appBuilder => appBuilder
.UseRoutable(routable => routable
.AddRouting(new DefaultRouting(routable, options, profileManager))
.OnError(new KestrelRouting(routable) {
_ => _.Do((context, request, response) => {
response.Status = 500;
response.ClearPendingWrites();
Log.Error(typeof(Program), $"A request encountered an unhandled exception.", context.Error);
})
})
)
)
.Build();
using var cancellation = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) => {
cancellation.Cancel();
e.Cancel = true;
};
await server.RunAsync(cancellation.Token);
Notes
- This does not occur when debugging on Windows using Visual Studio or running on Windows via
dotnet run
. - The executable is published as follows:
dotnet publish -o publish/ -r linux-musl-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true /p:IncludeNativeLibrariesForSelfExtract=true /p:IncludeAllContentForSelfExtract=true src/PROJECT_NAME
(edit: cleaned up structure a bit, added note)
Issue Analytics
- State:
- Created 3 years ago
- Comments:12 (6 by maintainers)
@davidfowl, yep, I’m happy. Thanks guys.
My email is in my github profile. I can forward it to @davidfowl if he’s interested internally.