下面又到了老周誤人子弟的時間,今天要誤大夥的話題是:找找有多少種方法可以設定 ASP.NET Core 應用的地址,即 URL。
精彩馬上開始!
這是一個擴充套件方法,引數是可變個數的字串陣列。所以,每傳一個引數就代表一個 URlL。例如
var builder = WebApplication.CreateBuilder(args); // 在 Build 之前要改好設定 builder.WebHost.UseUrls( "http://localhost:7979", "http://127.0.0.1:45125", "http://localhost:11600" ); var app = builder.Build(); // 此處省略 270 個 Unicode 字元
就這樣,咱們就輕鬆地設定了三個地址。程式執行後,存取任意一個地址均可。
這也是一個擴充套件方法,key 是「urls」,可以通過 WebHostDefaults.ServerUrlsKey 靜態欄位獲得,value 是URL 的值,多個 URL 用分號隔開。注意,URL 開頭不能有空格。下面的寫法是錯誤的。
var builder = WebApplication.CreateBuilder(args); // 在 Build 之前要改好設定 builder.WebHost.UseSetting(WebHostDefaults.ServerUrlsKey, "http://localhost:1188; http://localhost:57578");
第二個URL開始處多了一個空格,程式執行後會「呵呵」。
可以用 UseUrls 方法替代,它內部也是呼叫了 UseSetting 方法。
專案模板預設生成了一個 appsettings.json 檔案,我們可以直接用(可以新增自己定義的檔案,設定原理一樣)。
{ ……, "AllowedHosts": "*", "urls": "http://127.0.0.1:8968;http://192.168.0.107:21032" }
一樣,多個 URL 要用分號分隔。這種設定方法非常好,因為它和程式碼分離了,修改組態檔後儲存即可,不需要重新編譯應用程式。
這個檔案是在本地偵錯時使用的,一般在 Visual Studio 中使用。在 dotnet 命令列中也可以通過 --launch-profile 引數來指定要載入 launchSettings.json 檔案中哪個設定。這些設定都寫在 profiles 節點下。
"profiles": { "demo": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "http://localhost:5079", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, …… }
lanuchSettings.json 檔案可以進行多環境偵錯,比如上面程式碼設定了一個名為 demo 的環境,commandName = Project 表示用內建的 Kestrel 伺服器來執行,當然你可以選「IIS」等。
其中,applicationUrl 欄位用來設定應用程式的地址。
在 VS 中,直接從偵錯專案的下拉選單中選擇哪個環境執行即可。如果使用 dotnet 命令列,可以這樣:
dotnet run --launch-profile demo
呼叫 builder.Build 方法後,建立 WebApplication 範例(變數 app),它有個 Urls 屬性,集合型別,可以向其中新增 URL。
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.Urls.Add("http://localhost:3377"); app.Urls.Add("http://localhost:16852"); app.MapGet("/", () => "Hello World!"); app.Run();
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("http://localhost:8715");
WebApplication 類的 Run 或者 RunAsync 方法有接收 url 引數的過載。這種方法只能指定一個 URL,不能用分號來分隔多個 URL。
var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapGet("/", () => "Hello World!"); app.Run("http://localhost:12345");
這個地方只能設定一個 URL,而且會把其他方式設定的 URL 刪除。比如,你用 UseUrls 設定了URL,用環境變數設定了URL,但到了 Run 方法處,一旦你傳遞了 URL,就會把前面所設定的 URL 清空,最終只剩下傳遞給 Run 方法的 URL。
命令列的傳遞方法有以下幾種:
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
通過修改 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 的提示。如圖
至於原因,老周稍後會解釋。
Kestrel 是跨平臺的 Web 伺服器,而 HTTP.sys 只能用在 Windows 上。HTTP.sys 也是 ASP.NET Core 應用內建的伺服器。
var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseHttpSys(option => { option.UrlPrefixes.Add("http://localhost:30775"); }); var app = builder.Build(); // 此處丟失 105 個字元
使用了 HTTP.sys 設定的 URL,執行後同樣輸出 URL 覆蓋提示。下面馬上說明原因。
前面大夥們都看到了,當通過 Kestrel 或 HTTP.sys 設定 URL 後,執行程式就會有 URL 覆蓋提示。即通過 IServer 設定的 URL 替代了 WebHostBuilder 擴充套件方法所設定的 URL。
例如,下面程式同時使用 UseUrls 方法和 Kestrel 來設定 URL,執行後,UseUrls 所設定的 URL 會被 Kestrel 所設定的 URL 替換。
var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseUrls("http://localhost:6780"); builder.WebHost.ConfigureKestrel(opt => { opt.ListenLocalhost(29800); }); var app = builder.Build();
最終應用程式會選擇在 http://localhost:29800 上監聽。
如果你想忽略掉 Kestrel 的設定,仍然使用 UseUrls 的設定,就要呼叫 PreferHostingUrls 方法,並且傳遞 true 給 preferHostingUrls 引數。比如,把上面的程式碼改一下。
var builder = WebApplication.CreateBuilder(args); builder.WebHost.UseUrls("http://localhost:6780"); builder.WebHost.ConfigureKestrel(opt => { opt.ListenLocalhost(29800); }); builder.WebHost.PreferHostingUrls(true); var app = builder.Build();
這時候應用程式就會優先選擇 http://localhost:6780 地址。如下圖所示。