C# 如何配置Kestrel以使用随机动态端口,并在运行时使用ASP.NET Core 3.1确定端口?

C# 如何配置Kestrel以使用随机动态端口,并在运行时使用ASP.NET Core 3.1确定端口?,c#,asp.net-core,asp.net-core-3.1,C#,Asp.net Core,Asp.net Core 3.1,有了ASP.NET Core 3.0,我已经能够使用此IHostedService方法 。。。在运行时确定红隼的动态端口 ISERVERAddresssFeature在这里为ASP.NET 3.0提供了文档: 但是,当将版本更改为ASP.NET Core 3.1时,页面将重定向回ASP.NET 3.0,并提示该文档不适用于ASP.NET Core 3.1。ISERVERAddresssFeature是否不再工作?在ASP.NET Core 3.1中使用ISERVERAddresssFeatu

有了ASP.NET Core 3.0,我已经能够使用此
IHostedService
方法

。。。在运行时确定红隼的动态端口

ISERVERAddresssFeature
在这里为ASP.NET 3.0提供了文档:

但是,当将版本更改为ASP.NET Core 3.1时,页面将重定向回ASP.NET 3.0,并提示该文档不适用于ASP.NET Core 3.1。
ISERVERAddresssFeature
是否不再工作?在ASP.NET Core 3.1中使用
ISERVERAddresssFeature
仍然可以编译,但返回的
ServerAddresses
中的端口始终为零

节目:

public class Program
{
    public static void Main(string[] args)
    {
        BuildWebHost().Run();
    }

    public static IWebHost BuildWebHost() =>

        WebHost.CreateDefaultBuilder()
            .UseKestrel()
            .UseUrls("http://127.0.0.1:0") // port zero to use random dynamic port
            .UseStartup<Startup>()
            .Build();
}
。。。服务器地址分配给
HostedService.ServerAddresses
静态变量,如链接示例所示。但是,
ServerAddresses
仅包含端口为零的环回地址:
“http://127.0.0.1:0“

我是不是忽略了什么?在v3.1中是否有不同的、正确的方法来解决问题?如何配置Kestrel以使用随机动态端口,并使用ASP.NET Core 3.1在运行时(在任何控制器操作发生之前)确定它是哪个端口

更新

这里有一个难看的解决方法,可以帮助确定端口。动态端口分配的时间或顺序似乎发生了变化。从HostedService.StartAsync方法返回并稍后读取服务器地址似乎就足够了。肯定有更好的办法吗

        public Task StartAsync(CancellationToken cancellationToken)
        {
            System.Threading.Tasks.Task.Run(async () =>
            {
                int port = 0;
                while (port == 0)
                {
                    await System.Threading.Tasks.Task.Delay(250);
                    var address = ServerAddresses.Addresses.FirstOrDefault();
                    if (string.IsNullOrEmpty(address))
                        continue;
                    // address is always in form http://127.0.0.1:port
                    var pos = address.LastIndexOf(':');
                    if (pos > 0)
                    {
                        var portString = address.Substring(pos + 1);
                        port = int.Parse(portString);
                    }
                }
                // have determined the dynamic port now
            });
            return System.Threading.Tasks.Task.CompletedTask;
        }

IHostedService方法不起作用的原因是执行IHostedService时.Net Core 3发生了更改。在.NETCore2中,IHostedService在主机启动后执行,因此服务器地址信息随时可用。在.Net Core 3中,IHostedService在构建主机后运行,但在主机启动且地址不可用之前运行。对发生的变化有很好的解释

以下获取绑定地址(从复制)的方法适用于.Net Core 2和3

您可以调用
IWebHost.Start()
而不是建议的
IWebHost.Run()
。这将允许继续执行
Main
方法,以便您可以从
IWebHost.ServerFeatures
获取所需信息。请记住,除非您明确告诉应用程序不要使用
IWebHost.waitForShutton()
,否则应用程序将立即关闭

publicstaticvoidmain(字符串[]args)
{
var host=new WebHostBuilder()
.UseStartup()
.useURL(“http://*:0”)//这允许绑定到随机端口
.Build();
host.Start();
foreach(host.ServerFeatures.Get().Addresses中的var地址)
{
var uri=新的uri(地址);
var-port=uri.port;
WriteLine($“绑定到端口:{port}”);
}
//告诉主机阻止线程,就像host.Run()阻止线程一样。
host.waitForShutton();
}
        public Task StartAsync(CancellationToken cancellationToken)
        {
            System.Threading.Tasks.Task.Run(async () =>
            {
                int port = 0;
                while (port == 0)
                {
                    await System.Threading.Tasks.Task.Delay(250);
                    var address = ServerAddresses.Addresses.FirstOrDefault();
                    if (string.IsNullOrEmpty(address))
                        continue;
                    // address is always in form http://127.0.0.1:port
                    var pos = address.LastIndexOf(':');
                    if (pos > 0)
                    {
                        var portString = address.Substring(pos + 1);
                        port = int.Parse(portString);
                    }
                }
                // have determined the dynamic port now
            });
            return System.Threading.Tasks.Task.CompletedTask;
        }
 public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseStartup<Startup>()
            .UseUrls("http://*:0") // This enables binding to random port
            .Build();

        host.Start();

        foreach(var address in host.ServerFeatures.Get<IServerAddressesFeature>().Addresses)
        {
            var uri = new Uri(address);
            var port = uri.Port;

            Console.WriteLine($"Bound to port: {port}");
        }

        //Tell the host to block the thread just as host.Run() would have.
        host.WaitForShutdown();
    }