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

2022-06-06 15:07:19

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

精彩馬上開始!

 

1、UseUrls 方法

這是一個擴充套件方法,引數是可變個數的字串陣列。所以,每傳一個引數就代表一個 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 字元

就這樣,咱們就輕鬆地設定了三個地址。程式執行後,存取任意一個地址均可。

 

2、UseSetting 方法

這也是一個擴充套件方法,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 方法。

 

3、組態檔

專案模板預設生成了一個 appsettings.json 檔案,我們可以直接用(可以新增自己定義的檔案,設定原理一樣)。

{
  ……,
  "AllowedHosts": "*",
  "urls": "http://127.0.0.1:8968;http://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": "http://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("http://localhost:3377");
app.Urls.Add("http://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("http://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("http://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("http://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("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 地址。如下圖所示。