在运行时更改 Kestrel 端口

Change Kestrel port at runtime

我的项目使用 .net core 3.1,是一个使用内置服务器 Kestrel 的网络应用。
我在 CreateWebHostBuilder() 期间使用 .UseUrls("http://0.0.0.0:1234") 设置端口并正常工作。

在我的界面中,我希望用户能够在运行时更改端口。
但是我必须使用新保存的配置重新启动应用程序才能使其正常工作。
有没有关于如何在运行时更改它的提示?

public void Configure(IApplicationBuilder app)
{
    var address = app.ServerFeatures.Get<IServerAddressesFeature>();
    address.Addresses.Clear();
    address.Addresses.Add("http://*:5556");
}

我解决了(又快又脏)Kestrel 的重启服务器功能。
此方法只是一种 hack,不应在生产中使用。也许有一些聪明的头脑可以使它变得更好。

public class Program
{
    //Simple bool to tell the host to load again
    public static bool RestartWebserver { get; set; } = false;
    
    //Port to use
    public static int HttpPort { get; set; } = 80;

    //Main program
    public static int Main(string[] args)
    {
        //Infinityloop if 
        while(true)
        {
            CreateWebHostBuilder(args, Directory.GetCurrentDirectory()).Build().Run();
            
            //If RestartWebserver is false, exit everything...
            if (!RestartWebserver)
            {
                Console.WriteLine("Restarting...");
                break;
            }
            
            //Reset for the "new" host to be created.
            RestartWebserver = false;
        }
    }

    //Helper for creating host, returns a IWebHostBuilder to be Build and runned.
    public static IWebHostBuilder CreateWebHostBuilder(string[] args, string ContentRoot)
    {
        var Address = "0.0.0.0";
        string http = "http://" + Address + ":" + HttpPort;

        //Add arguments to the config (we could have a port set here too..)
        var configuration = new ConfigurationBuilder()
                .AddCommandLine(args)
                .Build();
        Startup.Configuration = configuration;

        //Return Webhost
        return WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .UseContentRoot(ContentRoot)
            .UseKestrel()
            .UseUrls(new string[] { http }));
    }
}

//Now in any controller you can force close the host like this
public class RestartController : Controller
{
    public IHostApplicationLifetime _applicationLifetime;
    
    public StatusController(IHostApplicationLifetime applicationLifetime)
    {
        _applicationLifetime = applicationLifetime;
    }

    public async Task<IActionResult> Index()
    {
        //Set new port
        Program.HttpPort = 12345;
        
        //Set the server to restart
        Program.RestartWebserver = true;
        
        //Quit current host
        _applicationLifetime.StopApplication();

        //This function will fail.
        //Suggest to create a javascript file to reload client to the new port...
        return View("Index");
    }
}

这个方法对我有用,但是上面的代码有点像 sudo,它从来没有以它的形式编译过。虽然概念已在 dotnet v5.0.100

上进行了测试和确认