下面又到了老周误人子弟的时间,今天要误大伙的话题是:找找有多少种方法可以设置 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 地址。如下图所示。