如何在不访问请求的情况下获取基本URL

时间:2016-10-05 02:31:04

标签: asp.net-core asp.net-core-mvc base-url

如何在没有请求的情况下在AspNet核心应用程序中获取基本URL?

我从请求中知道您可以获得方案和主机(即$"{Request.Scheme}//{Request.Host}"会提供类似https://localhost:5000的内容),但是否可以从其他任何地方获取此信息?

换句话说,如果我有一个需要构建绝对URL的服务类,当没有可用的http请求时,如何获取当前URL?

更新:也许这种情况甚至没有意义,因为托管URL完全在应用程序外部,这就是为什么从请求主机中提取它只是有意义的。

3 个答案:

答案 0 :(得分:10)

我出于某种原因需要在Start.cs Configure中获取基本URL,所以我想出了这个

formItem

答案 1 :(得分:7)

您是对的,托管URL是一种外部信息,您只需将其作为配置参数传递给您的应用程序。

也许这会以某种方式帮助你:没有请求,你可以使用IWebHostBuilder接口获得配置的监听地址(如http://+:5000)。它通过GetSetting方法提供对主机设置的访问:

/// <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)并获取当前值。

答案 2 :(得分:1)

,ASP.NET Core模块生成一个动态端口以分配给后端进程。 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类的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;
        }
    }