Kestrel http server 如何确定在指定动态端口(0)时ASP.NET Core 2正在侦听的端口

Kestrel http server 如何确定在指定动态端口(0)时ASP.NET Core 2正在侦听的端口,kestrel-http-server,asp.net-core-2.0,Kestrel Http Server,Asp.net Core 2.0,我有一个ASP.NET Core 2.0应用程序,我打算作为一个独立的应用程序运行。应用程序应启动并绑定到可用端口。为了实现这一点,我将WebHostBuilder配置为侦听“”并使用Kestrel服务器。一旦web主机开始侦听,我想将url与实际端口一起保存在一个文件中。我希望尽早这样做,因为另一个应用程序将读取该文件以与我的应用程序交互 如何确定web主机正在侦听的端口?我可以使用反射(啊!)。我已经注册了一个IHostedService并注入了IServer。KestrelServerOp

我有一个ASP.NET Core 2.0应用程序,我打算作为一个独立的应用程序运行。应用程序应启动并绑定到可用端口。为了实现这一点,我将WebHostBuilder配置为侦听“”并使用Kestrel服务器。一旦web主机开始侦听,我想将url与实际端口一起保存在一个文件中。我希望尽早这样做,因为另一个应用程序将读取该文件以与我的应用程序交互


如何确定web主机正在侦听的端口?

我可以使用反射(啊!)。我已经注册了一个
IHostedService
并注入了
IServer
KestrelServerOptions
上的
ListenOptions
属性是内部的,因此我需要使用反射来访问它。调用托管服务后,我使用以下代码提取端口:

var options = ((KestrelServer)server).Options;
var propertyInfo = options.GetType().GetProperty("ListenOptions", BindingFlags.Instance | BindingFlags.NonPublic);
var listenOptions = (List<ListenOptions>)propertyInfo.GetValue(options);
var ipEndPoint = listenOptions.First().IPEndPoint;
var port = ipEndPoint.Port;
int Url = new System.Uri(Configuration["urls"]).Port;
var选项=((KestrelServer)服务器);
var propertyInfo=options.GetType().GetProperty(“ListenOptions”,BindingFlags.Instance | BindingFlags.NonPublic);
var listenOptions=(列表)propertyInfo.GetValue(选项);
var ipEndPoint=listenOptions.First().ipEndPoint;
var port=ipEndPoint.port;

您可以在方法配置的启动类中实现它。您可以从ServerAddressesFeature获取端口

下面是一个代码示例:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ILogger<Startup> logger)
{
     var serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();

     loggerFactory.AddFile("logs/myfile-{Date}.txt", minimumLevel: LogLevel.Information, isJson: false);

     logger.LogInformation("Listening on the following addresses: " + string.Join(", ", serverAddressesFeature.Addresses));
}
public void配置(IApplicationBuilder应用程序、IHostingEnvironment环境、ILoggerFactory loggerFactory、ILogger logger)
{
var serverAddressesFeature=app.ServerFeatures.Get();
loggerFactory.AddFile(“logs/myfile-{Date}.txt”,minimumLevel:LogLevel.Information,isJson:false);
logger.LogInformation(“侦听以下地址:”+string.Join(“,”,serverAddressesFeature.addresses));
}

您可以使用
Start()
方法而不是
Run()
在适当的时候访问
ISERVERAddresssFeature

IWebHost webHost = new WebHostBuilder()
    .UseKestrel(options => 
         options.Listen(IPAddress.Loopback, 0)) // dynamic port
    .Build();

webHost.Start();

string address = webHost.ServerFeatures
    .Get<IServerAddressesFeature>()
    .Addresses
    .First();
int port = int.Parse(address.Split(':').Last());

webHost.WaitForShutdown();
IWebHost webHost=new WebHostBuilder()
.UseKestrel(选项=>
options.Listen(IPAddress.Loopback,0))//动态端口
.Build();
webHost.Start();
字符串地址=webHost.ServerFeatures
.Get()
.地址
.First();
int port=int.Parse(address.Split(':').Last());
webHost.WaitForShutdown();

我可以在StartUp.cs中使用以下代码完成此操作:

var options = ((KestrelServer)server).Options;
var propertyInfo = options.GetType().GetProperty("ListenOptions", BindingFlags.Instance | BindingFlags.NonPublic);
var listenOptions = (List<ListenOptions>)propertyInfo.GetValue(options);
var ipEndPoint = listenOptions.First().IPEndPoint;
var port = ipEndPoint.Port;
int Url = new System.Uri(Configuration["urls"]).Port;

至少从.NETCore3中,您可以注入
IServer
并获取信息

using System;
using System.Linq;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Hosting.Server.Features;

namespace MyApp.Controllers
{
    public class ServerInfoController : Controller
    {
        public ServerInfoController (IServer server)
        {
            var addresses = server.Features.Get<IServerAddressesFeature>()?.Addresses?.ToArray();
        }
    }
}
使用系统;
使用System.Linq;
使用Microsoft.AspNetCore.Hosting.Server;
使用Microsoft.AspNetCore.Hosting.Server.Features;
名称空间MyApp.Controllers
{
公共类ServerInfoController:控制器
{
公共服务器InfoController(IServer服务器)
{
var addresses=server.Features.Get()?.addresses?.ToArray();
}
}
}

有0个地址,你知道为什么吗?你确定@jjxtra?它是枚举器,所以您必须执行以下操作:
foreach(serverAddressesFeature.Addresses中的var地址)Console.WriteLine(address.ToString())
而不是使用
Console.ReadKey()
使用
webHost.WaitForShutdown()
您应该使用
int.Parse(address.Split(':').Last())
由于地址可以定义为IPv6地址,因此如果您希望在获取地址之前在控制台/输出中打印默认消息,也可以使用
webHost.RunAsync()
而不是
webHost.Start()
。如果在两个端口(一个用于HTTP,另一个用于HTTPS)上侦听,则此操作将不起作用对于.NET Core 3.1
Configuration[“URL”]
而言,在
Startup.Configure()
中返回null,因此此建议似乎不起作用。这是一个不完整的答案。。无法解析类型为“Microsoft.AspNetCore.Hosting.Server.IServer”的服务@Gabrieluca如果未调用
WebHost.CreateDefaultBuilder
,则可能存在未注册
IServer
的问题
ConfigureKestrel
不注册
IServer
,但
UseKestrel
CreateDefaultBuilder
do。我也调用了WebHost.CreateDefaultBuilder,但仍然无法工作。。。我会收回我的反对票,因为。。。奇怪的是M$是如何改变事情的,而这么简单的事情很难做到。。得到。。我不能改变我的投票,除非你改变答案。。。它不允许我如果你能让它工作的话。。发布一个小样本,这会有所帮助。。