如何在不访问请求的情况下获取基数 url
How to get base url without accessing a request
如何在没有请求的情况下在 AspNet 核心应用程序中获取基础 URL?
我从请求中知道您可以获得方案和主机(即 $"{Request.Scheme}://{Request.Host}"
会给出类似 https://localhost:5000 的信息),但是是否可以从其他任何地方获取此信息?
换句话说,如果我有一个服务class需要构建绝对URLs,当没有可用的http请求时,我如何获取当前URL ?
更新:也许这种情况甚至没有意义,因为托管 URL 完全在应用程序外部,这就是为什么只有从请求主机中提取它才有意义..
你是对的,托管 URL 是一个外部信息,你可以简单地将它作为配置参数传递给你的应用程序。
也许这会以某种方式帮助您:无需请求,您可以使用 IWebHostBuilder interface. It provides access to host settings via the GetSetting
方法获得配置的监听地址(如 http://+:5000
):
/// <summary>
/// Get the setting value from the configuration.
/// </summary>
/// <param name="key">The key of the setting to look up.</param>
/// <returns>The value the setting currently contains.</returns>
string GetSetting(string key);
有一个WebHostDefaults.ServerUrlsKey设置名称,允许配置监听地址。我们在添加 .UseUrls
扩展方法时覆盖它:
public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls);
或定义urls
配置参数,如the documentation中所述(你知道,默认情况下监听配置为localhost:5000
)。
因此,有了 IWebHostBuilder
的实例,您可以调用 .GetSetting(WebHostDefaults.ServerUrlsKey)
并获取当前值。
出于某种原因我需要在 Start.cs 配置中获取基础 URL,所以我想出了这个
var URLS = app.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
,ASP.NET核心模块生成动态端口分配给后端进程。 CreateDefaultBuilder 调用 UseIISIntegration 方法。 UseIISIntegration 将 Kestrel 配置为侦听本地主机 IP 地址 (127.0.0.1) 的动态端口。如果动态端口为 1234,则 Kestrel 会在 127.0.0.1:1234 进行侦听。此配置替换由提供的其他 URL 配置。
对于 IIS 集成,如果您在 WebHostBuilder.Build() 具有 运行 之后获取地址,它就可以工作。
var builder = CreateWebHostBuilder(args);
var webHost = builder.Build();
var addresses = webHost.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
var address = addresses.FirstOrDefault();
AppDomain.CurrentDomain.SetData("BaseUrl", address ?? "");
webHost.Run();
并在 HostedService 中获取本地 Kestrel 地址,如下所示:
string baseUrl = AppDomain.CurrentDomain.GetData("BaseUrl").ToString();
但是有一个问题 - 这个地址是无用的,因为你不能直接在这个地址上发出请求。 IIS 集成中间件检查是否只有 IIS 处理程序可以对该地址发出请求。它会产生类似的错误:
<category>Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware</category>
<state>'MS-ASPNETCORE-TOKEN' does not match the expected pairing token 'ed5bc610-b7b9-4c1c-9941-954d0579edfc', request rejected.</state>
并且在一般情况下(没有 IIS 集成)如果您使用配置为 运行 且具有自定义端口(不是 5000)或动态端口 0 的 Kestrel,则这种获取地址的方法不起作用。在这种情况下需要延迟获取地址,只有在应用启动后才能获取。
对于这种情况,我尝试了这种方式:在 StartUp class 的 Configure 方法中,我保存在私有成员的 ServerAddressFeature 中。
private IServerAddressesFeature _serverAddressesFeature;
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
_serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
... not related code here ...
并且在 ConfigureServices 方法中我添加了一个依赖项
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IServerAddressesFeature>((sp) => _serverAddressesFeature);
... not related code here ...
然后在托管服务中,我使用依赖注入获得了这个保存的特征,并用它来获取地址。
有效,只在StartAsync方法中获取地址,不在服务构造函数中!
public class WarmUpService : IHostedService
{
private readonly ILogger _logger;
private readonly IServerAddressesFeature _saf;
public WarmUpService(ILogger<WarmUpService> logger, IServerAddressesFeature serverAddressesFeature)
{
_logger = logger;
_saf = serverAddressesFeature;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
try
{
// the URL can be Got here
string baseUrl = _saf?.Addresses?.FirstOrDefault();
// await _WarmUp(baseUrl);
}
catch(Exception ex)
{
_logger.LogCritical(ex, "WarmUp Failed");
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
如何在没有请求的情况下在 AspNet 核心应用程序中获取基础 URL?
我从请求中知道您可以获得方案和主机(即 $"{Request.Scheme}://{Request.Host}"
会给出类似 https://localhost:5000 的信息),但是是否可以从其他任何地方获取此信息?
换句话说,如果我有一个服务class需要构建绝对URLs,当没有可用的http请求时,我如何获取当前URL ?
更新:也许这种情况甚至没有意义,因为托管 URL 完全在应用程序外部,这就是为什么只有从请求主机中提取它才有意义..
你是对的,托管 URL 是一个外部信息,你可以简单地将它作为配置参数传递给你的应用程序。
也许这会以某种方式帮助您:无需请求,您可以使用 IWebHostBuilder interface. It provides access to host settings via the GetSetting
方法获得配置的监听地址(如 http://+:5000
):
/// <summary>
/// Get the setting value from the configuration.
/// </summary>
/// <param name="key">The key of the setting to look up.</param>
/// <returns>The value the setting currently contains.</returns>
string GetSetting(string key);
有一个WebHostDefaults.ServerUrlsKey设置名称,允许配置监听地址。我们在添加 .UseUrls
扩展方法时覆盖它:
public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls);
或定义urls
配置参数,如the documentation中所述(你知道,默认情况下监听配置为localhost:5000
)。
因此,有了 IWebHostBuilder
的实例,您可以调用 .GetSetting(WebHostDefaults.ServerUrlsKey)
并获取当前值。
出于某种原因我需要在 Start.cs 配置中获取基础 URL,所以我想出了这个
var URLS = app.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
,ASP.NET核心模块生成动态端口分配给后端进程。 CreateDefaultBuilder 调用 UseIISIntegration 方法。 UseIISIntegration 将 Kestrel 配置为侦听本地主机 IP 地址 (127.0.0.1) 的动态端口。如果动态端口为 1234,则 Kestrel 会在 127.0.0.1:1234 进行侦听。此配置替换由提供的其他 URL 配置。
对于 IIS 集成,如果您在 WebHostBuilder.Build() 具有 运行 之后获取地址,它就可以工作。
var builder = CreateWebHostBuilder(args);
var webHost = builder.Build();
var addresses = webHost.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
var address = addresses.FirstOrDefault();
AppDomain.CurrentDomain.SetData("BaseUrl", address ?? "");
webHost.Run();
并在 HostedService 中获取本地 Kestrel 地址,如下所示:
string baseUrl = AppDomain.CurrentDomain.GetData("BaseUrl").ToString();
但是有一个问题 - 这个地址是无用的,因为你不能直接在这个地址上发出请求。 IIS 集成中间件检查是否只有 IIS 处理程序可以对该地址发出请求。它会产生类似的错误:
<category>Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware</category>
<state>'MS-ASPNETCORE-TOKEN' does not match the expected pairing token 'ed5bc610-b7b9-4c1c-9941-954d0579edfc', request rejected.</state>
并且在一般情况下(没有 IIS 集成)如果您使用配置为 运行 且具有自定义端口(不是 5000)或动态端口 0 的 Kestrel,则这种获取地址的方法不起作用。在这种情况下需要延迟获取地址,只有在应用启动后才能获取。
对于这种情况,我尝试了这种方式:在 StartUp class 的 Configure 方法中,我保存在私有成员的 ServerAddressFeature 中。
private IServerAddressesFeature _serverAddressesFeature;
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
_serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
... not related code here ...
并且在 ConfigureServices 方法中我添加了一个依赖项
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IServerAddressesFeature>((sp) => _serverAddressesFeature);
... not related code here ...
然后在托管服务中,我使用依赖注入获得了这个保存的特征,并用它来获取地址。 有效,只在StartAsync方法中获取地址,不在服务构造函数中!
public class WarmUpService : IHostedService
{
private readonly ILogger _logger;
private readonly IServerAddressesFeature _saf;
public WarmUpService(ILogger<WarmUpService> logger, IServerAddressesFeature serverAddressesFeature)
{
_logger = logger;
_saf = serverAddressesFeature;
}
public async Task StartAsync(CancellationToken cancellationToken)
{
try
{
// the URL can be Got here
string baseUrl = _saf?.Addresses?.FirstOrDefault();
// await _WarmUp(baseUrl);
}
catch(Exception ex)
{
_logger.LogCritical(ex, "WarmUp Failed");
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}