.NET Core 6.0 - 获取Kestrel的动态绑定端口(端口0)

.NET Core 6.0 - Get Kestrel's dynamically bound port (port 0)

上下文

“托管”机制在 .NET 6 中发生了变化。以前 IWebHostIWebHost.ServerFeatures 属性 可以用来像这样获取 IServerAddressFeature(来自):

IWebHost 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}");
}

问题:如何使用 IHost 在 .NET 6 中获取端口?

现在在 .NET 6 中我有一个 IHost。如何获取端口(符合 ???):

public class Program {
  public static void Main(string[] args) {
    IHostBuilder hostBuilder = Host.CreateDefaultBuilder(args);
    hostBuilder.ConfigureWebHostDefaults(webHostBuilder => {
      webHostBuilder.ConfigureKestrel(opts => {
        opts.ListenAnyIP(0); // bind web server to random free port
      });
      webHostBuilder.UseStartup<Startup>();
    });
    IHost host = hostBuilder.Build();
    host.Start();
    // If it doesn't fail, at this point Kestrel has started
    // and is listening on a port. It even prints the port to
    // console via logger.
    int boundPort = ???; // some magic GetPort(IHost host) method

    // This link in the docs mentions getting the port, but the example
    // they provide is incomplete
    // https://docs.microsoft.com/en-us/aspnet/core/fundamentals/servers/kestrel/endpoints?view=aspnetcore-6.0#port-0
    host.WaitForShutdown();
  }
}

微软文档中的示例:

指定端口号 0 时,Kestrel 会动态绑定到一个可用端口。以下示例显示了如何确定 Kestrel 在运行时绑定的端口:

app.Run(async (context) =>
{
    var serverAddressFeature = context.Features.Get<IServerAddressesFeature>();

    if (serverAddressFeature is not null)
    {
        var listenAddresses = string.Join(", ", serverAddressFeature.Addresses);

        // ...
    }
});

在此示例中,app 是什么?我在哪里可以用 .Features 得到 context

发布问题后立即找到有效答案。 在 .NET 6 中打印正在运行的 Web 服务器地址(包括端口)的函数。 原来我们对主机中 IServer 服务的 运行 实例感兴趣。

public static void PrintBoundAddressesAndPorts(IHost host)
{
    Console.WriteLine("Checking addresses...");
    var server = host.Services.GetRequiredService<IServer>();
    var addressFeature = server.Features.Get<IServerAddressesFeature>();
    foreach(var address in addressFeature.Addresses)
    {
        var uri = new Uri(address);
        var port = uri.Port;
        Console.WriteLine($"Listing on [{address}]");
        Console.WriteLine($"The port is [{port}]");
    }
}

在这篇文章中找到了答案:https://andrewlock.net/finding-the-urls-of-an-aspnetcore-app-from-a-hosted-service-in-dotnet-6/