リクエストなしでAspNetコアアプリケーションでベースURLを取得する方法は?
リクエストからスキームとホストを取得できることを知っています(つまり$"{Request.Scheme}//{Request.Host}"
は https:// localhost:50 )のようになりますが、他のどこからでもこの情報を取得することは可能ですか?
つまり、絶対URLを構築する必要があるサービスクラスがある場合、httpリクエストが利用できないときに現在のURLを取得するにはどうすればよいですか?
更新:ホスティングURLはアプリケーションの外部にあるため、このシナリオは意味をなさないかもしれません。それが、リクエストホストから抽出することだけが理にかなっている理由です。
ホスティング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
構成パラメーターを定義します(デフォルトでは、リスニングは_localhost:5000
_に構成されています)。
したがって、IWebHostBuilder
のインスタンスを使用して、.GetSetting(WebHostDefaults.ServerUrlsKey)
を呼び出して現在の値を取得できます。
start.cs ConfigureでベースURLを取得するために何らかの理由で必要だったので、これを思い付きます
var URLS = app.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
ASP.NET Core Moduleは、バックエンドプロセスに割り当てる動的ポートを生成します。 CreateDefaultBuilderはUseIISIntegrationメソッドを呼び出します。 UseIISIntegrationは、localhost IPアドレス(127.0.0.1)の動的ポートでリッスンするようにKestrelを構成します。動的ポートが1234の場合、Kestrelは127.0.0.1:1234でリッスンします。この構成は、提供されている他のURL構成を置き換えます。
IIS Integrationの場合、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>
また、一般的な場合(no IIS Integration)では、カスタムポート(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;
}
}