问题描述
我正在使用ASP.NET Core空(web
)模板编写一个简单的ASP.NET Core服务.
I'm writing a simple ASP.NET Core service using ASP.NET Core empty (web
) template.
默认情况下,它绑定到端口5000,但我希望它绑定到系统上的随机可用端口.
By default, it binds to port 5000 but I would like it to bind to a random available port on the system.
我可以通过将BuildWebHost
修改为:
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://*:0") // This enables binding to random port
.Build();
它绑定到随机端口,但是如何从应用程序中确定我正在侦听哪个端口?
It binds to a random port but how do I determine from within the application which port I'm listening to?
推荐答案
可以通过IServerAddressesFeature.Addresses
集合访问ASP.NET Core应用程序的托管地址.
Hosting addresses of ASP.NET Core application could be accessed via IServerAddressesFeature.Addresses
collection.
主要挑战是调用代码,该代码将在正确的时间分析此集合.实际的端口绑定发生在调用IWebHost.Run()
时(从Program.Main()
开始).因此,您尚不能使用Startup.Configure()
方法访问托管地址,因为在此阶段尚未分配端口.调用IWebHost.Run()
后,您将失去控制,因为直到Web主机关闭,该调用才会返回.
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.
据我了解,分析绑定端口的最合适方法是通过实现 IHostedService .这是工作示例:
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;
}
}
在Startup
类中:
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>();
}
}
IServerAddressesFeature
的实例通过GetBindingHostedService
中的丑陋静态属性传递.我看不到如何将其注入服务中.
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.
总的来说,我对这种解决方案不满意.它可以完成工作,但是看起来比它应该的要复杂得多.
Overall I'm not happy with such solution. It does the job, however it seems much more complex than it should be.
这篇关于确定端口Kestrel绑定到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!