Hosting addresses of ASP.NET Core application could be accessed via IServerAddressesFeature.Addresses
collection.
The main challenge is to invoke the code, which will analyze this collection, at the right time. The actual port binding happens when IWebHost.Run()
is called (from Program.Main()
). Therefore you can't yet access hosting address in Startup.Configure()
method, because port has not been yet assigned on this stage. And you loose control after calling IWebHost.Run()
, because this call does not return untill web host is shut down.
In my understanding, the most suitable way to analyze bound port is through implementation of IHostedService. Here is working sample:
public class GetBindingHostedService : IHostedService
{
public static IServerAddressesFeature ServerAddresses { get; set; }
public Task StartAsync(CancellationToken cancellationToken)
{
var address = ServerAddresses.Addresses.Single();
var match = Regex.Match(address, @"^.+:(d+)$");
if (match.Success)
{
int port = Int32.Parse(match.Groups[1].Value);
Console.WriteLine($"Bound port is {port}");
}
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
In Startup
class:
public class Startup
{
// ...
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSingleton<IHostedService, GetBindingHostedService>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
GetBindingHostedService.ServerAddresses = app.ServerFeatures.Get<IServerAddressesFeature>();
}
}
Instance of IServerAddressesFeature
is passed through ugly static property in GetBindingHostedService
. I don't see other way how it could be injected into the service.
Sample Project on GitHub
Overall I'm not happy with such solution. It does the job, however it seems much more complex than it should be.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…