【ASP.NET Core】配置應用程式地址的N多種方法

下面又到了老周誤人子弟的時間,今天要誤大夥的話題是:找找有多少種方法可以設置 ASP.NET Core 應用的地址,即 URL。

精彩馬上開始!

 

1、UseUrls 方法

這是一個擴展方法,參數是可變個數的字元串數組。所以,每傳一個參數就代表一個 URlL。例如

var builder = WebApplication.CreateBuilder(args);
// 在 Build 之前要改好設置
builder.WebHost.UseUrls(
        "//localhost:7979",
        "//127.0.0.1:45125",
        "//localhost:11600"
    );

var app = builder.Build();
// 此處省略 270 個 Unicode 字元

就這樣,咱們就輕鬆地設置了三個地址。程式運行後,訪問任意一個地址均可。

 

2、UseSetting 方法

這也是一個擴展方法,key 是「urls」,可以通過 WebHostDefaults.ServerUrlsKey 靜態欄位獲得,value 是URL 的值,多個 URL 用分號隔開。注意,URL 開頭不能有空格。下面的寫法是錯誤的。

var builder = WebApplication.CreateBuilder(args);
// 在 Build 之前要改好設置
builder.WebHost.UseSetting(WebHostDefaults.ServerUrlsKey, "//localhost:1188; //localhost:57578");

第二個URL開始處多了一個空格,程式運行後會「呵呵」。

可以用 UseUrls 方法替代,它內部也是調用了 UseSetting 方法。

 

3、配置文件

項目模板默認生成了一個 appsettings.json 文件,我們可以直接用(可以添加自己定義的文件,配置原理一樣)。

{
  ……,
  "AllowedHosts": "*",
  "urls": "//127.0.0.1:8968;//192.168.0.107:21032"
}

一樣,多個 URL 要用分號分隔。這種配置方法非常好,因為它和程式碼分離了,修改配置文件後保存即可,不需要重新編譯應用程式。

 

4、launchSettings.json 文件

這個文件是在本地調試時使用的,一般在 Visual Studio 中使用。在 dotnet 命令行中也可以通過 --launch-profile 參數來指定要載入 launchSettings.json 文件中哪個配置。這些配置都寫在 profiles 節點下。

"profiles": {
    "demo": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "//localhost:5079",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
 ……
}

lanuchSettings.json 文件可以進行多環境調試,比如上面程式碼配置了一個名為 demo 的環境,commandName = Project 表示用內置的 Kestrel 伺服器來運行,當然你可以選「IIS」等。

其中,applicationUrl 欄位用來設置應用程式的地址。

在 VS 中,直接從調試項目的下拉列表中選擇哪個環境執行即可。如果使用 dotnet 命令行,可以這樣:

dotnet run --launch-profile demo

 

5、app.Urls 屬性

調用 builder.Build 方法後,創建 WebApplication 實例(變數 app),它有個 Urls 屬性,集合類型,可以向其中添加 URL。

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();
app.Urls.Add("//localhost:3377");
app.Urls.Add("//localhost:16852");

app.MapGet("/", () => "Hello World!");

app.Run();

 

6、使用 ServerAddressesFeature 對象

 IServerAddressesFeature 介面公開屬性 Addresses。

public System.Collections.Generic.ICollection<string> Addresses { get; }

此屬性表示一個字元串集合,用於設置程式的 URL,上面提到的 app.Urls 屬性實際上就是公開 Addresses 屬性。也就是說,app.Urls 屬性封裝了 Addresses 屬性。

IServerAddressesFeature 介面的默認實現類是 ServerAddressesFeature。但是,從依賴注入的服務容器中不能直接獲取到,因為它不是直接放進容器中的,而是作為了 IServer 的 Features 屬性中一個元素來引用的。

ASP.NET Core 應用程式啟動時默認會向服務容器添加一個實現了 IServer 的對象,嗯,說白了就是 Kestrel 伺服器。

下面是例子:

var app = builder.Build();

// Server 對象
var server = app.Services.GetRequiredService<IServer>();
// 獲取 IServerAddressesFeature
var addrfeature = server.Features.Get<IServerAddressesFeature>();
// 添加 URL
addrfeature?.Addresses.Add("//localhost:8715");

 

7、通過 app.Run 方法

WebApplication 類的 Run 或者 RunAsync 方法有接收 url 參數的重載。這種方法只能指定一個 URL,不能用分號來分隔多個 URL。

var builder = WebApplication.CreateBuilder(args);

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run("//localhost:12345");

這個地方只能配置一個 URL,而且會把其他方式配置的 URL 刪除。比如,你用 UseUrls 配置了URL,用環境變數配置了URL,但到了 Run 方法處,一旦你傳遞了 URL,就會把前面所配置的 URL 清空,最終只剩下傳遞給 Run 方法的 URL。

 

8、命令行參數和環境變數

命令行的傳遞方法有以下幾種:

dotnet abc.dll --urls http://localhost:8888
dotnet abc.dll --urls=http://abc.org
dotnet abc.dll /urls http://192.168.1.125:49035
dotnet abc.dll /urls=http://localhost:17156

環境變數也是叫「urls」,不過一般用大寫,而且注意帶上前綴 ASPNETCORE_,這是默認前綴,如果你修改過,就用自定義的前綴。

例如,在 Windows 上。

set ASPNETCORE_URLS=http://killer.com
dotnet abc.dll

在 XXnix 上

export ASPNETCORE_URLS=http://ddW.host.net
dotnet abc.dll

 

9、通過 Kestrel 伺服器來配置

通過修改 Kestrel 伺服器的配置也可以設置地址,但該配置是面向 Socket 層面的,以 IP + 埠的方式配置。

舉例:

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(kop =>
{
    kop.ListenAnyIP(5999);
    kop.ListenLocalhost(39824);
});

var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

KestrelServerOptions 類有以下幾種 ListenXXX 方法可選擇:

(1)Listen 方法:指定 IP 和埠。

(2)ListenLocalhost 方法:只監聽本機 IP,只需指定埠即可。

(3)ListenAnyIP 方法:監聽當前電腦上所有網卡的 IP,只需指定埠即可。

使用此法配置 URL 後,當運行應用程式時,會出現個覆蓋 URL 的提示。如圖

 

 至於原因,老周稍後會解釋。

 

10、通過 HTTP.sys 配置

 Kestrel 是跨平台的 Web 伺服器,而 HTTP.sys 只能用在 Windows 上。HTTP.sys 也是 ASP.NET Core 應用內置的伺服器。

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseHttpSys(option =>
{
    option.UrlPrefixes.Add("//localhost:30775");
});

var app = builder.Build();
// 此處丟失 105 個字元

 使用了 HTTP.sys 配置的 URL,運行後同樣輸出 URL 覆蓋提示。下面馬上說明原因。

 

收尾:PreferHostingUrls 方法

前面大夥們都看到了,當通過 Kestrel 或 HTTP.sys 配置 URL 後,運行程式就會有 URL 覆蓋提示。即通過 IServer 配置的 URL 替代了 WebHostBuilder 擴展方法所設置的 URL。

例如,下面程式同時使用 UseUrls 方法和 Kestrel 來配置 URL,運行後,UseUrls 所配置的 URL 會被 Kestrel 所配置的 URL 替換。

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("//localhost:6780");
builder.WebHost.ConfigureKestrel(opt =>
{
    opt.ListenLocalhost(29800);
});

var app = builder.Build();

最終應用程式會選擇在 //localhost:29800 上監聽。

如果你想忽略掉 Kestrel 的配置,仍然使用 UseUrls 的配置,就要調用 PreferHostingUrls 方法,並且傳遞 true 給 preferHostingUrls 參數。比如,把上面的程式碼改一下。

var builder = WebApplication.CreateBuilder(args);
builder.WebHost.UseUrls("//localhost:6780");
builder.WebHost.ConfigureKestrel(opt =>
{
    opt.ListenLocalhost(29800);
});

builder.WebHost.PreferHostingUrls(true);

var app = builder.Build();

這時候應用程式就會優先選擇 //localhost:6780 地址。如下圖所示。