web-dev-qa-db-fra.com

Comment obtenir l'URL de base sans accéder à une demande

Comment obtenir l'URL de base dans l'application principale AspNet sans avoir à demander?

Je sais que dans la demande, vous pouvez obtenir le schéma et l'hôte (c'est-à-dire que $"{Request.Scheme}//{Request.Host}" donnerait quelque chose comme https: // localhost: 5000 ), mais est-il possible d'obtenir cette information ailleurs?

En d'autres termes, si une classe de service doit créer des URL absolues, comment puis-je obtenir l'URL actuelle lorsqu'il n'y a pas de requête http disponible?

UPDATE: Ce scénario n’a peut-être même pas de sens puisque l’URL d’hébergement est totalement externe à l’application et c’est pourquoi il n’a de sens que de l'extraire de l'hôte de la demande.

16
iberodev

Vous avez raison, l'hébergement URL est une information externe que vous pouvez simplement transmettre en tant que paramètre de configuration à votre application.

Cela vous aidera peut-être d'une certaine manière: sans demande, vous pouvez obtenir une adresse d'écoute configurée (telle que http://+:5000) à l'aide de IWebHostBuilder interface. Il permet d'accéder aux paramètres de l'hôte via la méthode 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);

Il existe un WebHostDefaults.ServerUrlsKey nom du paramètre, qui permet de configurer une adresse d'écoute. Nous la substituons lorsque nous ajoutons la méthode d'extension .UseUrls:

public static IWebHostBuilder UseUrls(this IWebHostBuilder hostBuilder, params string[] urls);

ou définissez le paramètre de configuration urls comme décrit dans la documentation (vous savez, par défaut, Listening est configuré sur localhost:5000).

Ainsi, ayant une instance de IWebHostBuilder, vous pouvez appeler .GetSetting(WebHostDefaults.ServerUrlsKey) et obtenir la valeur actuelle.

7
Set

, Le module ASP.NET Core génère un port dynamique à affecter au processus d’arrière-plan. CreateDefaultBuilder appelle la méthode UseIISIntegration. UseIISIntegration configure Kestrel pour qu'il écoute sur le port dynamique à l'adresse IP de l'hôte local (127.0.0.1). Si le port dynamique est 1234, Kestrel écoute à 127.0.0.1:1234. Cette configuration remplace les autres configurations d’URL fournies par.

Pour l'intégration IIS, cela fonctionne si vous obtenez l'adresse après l'exécution de 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();

et a obtenu l'adresse Kestrel locale dans HostedService comme ceci:

  string baseUrl = AppDomain.CurrentDomain.GetData("BaseUrl").ToString();

Mais il y a un piège - cette adresse est inutile, car vous ne pouvez pas faire une demande directement sur cette adresse. Le middleware d'intégration IIS vérifie que seul le gestionnaire IIS peut effectuer une requête sur cette adresse. Cela produit une erreur similaire:

<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>

Et dans le cas général (pas d'intégration IIS), cette méthode d'obtention de l'adresse ne fonctionne pas si vous utilisez Kestrel configuré pour s'exécuter avec un port personnalisé (pas 5000) ou un port dynamique 0. Dans ce cas, l'adresse doit à obtenir de manière différée, uniquement après le démarrage de l'application.

Dans ce cas, j’ai essayé de cette façon: Dans la méthode Configure de la classe StartUp, j’ai enregistré dans ServerAddressFeature dans le membre privé.

  private IServerAddressesFeature _serverAddressesFeature;

  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  {
            _serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
          ... not related code here ...

Et dans la méthode ConfigureServices, j'ai ajouté une dépendance 

 public void ConfigureServices(IServiceCollection services)
 {
     services.AddSingleton<IServerAddressesFeature>((sp) => _serverAddressesFeature);
  ... not related code here ...

Ensuite, dans un service hébergé, j'obtiens cette fonctionnalité enregistrée à l'aide de l'injection de dépendance et l'utilise pour obtenir l'adresse. Cela fonctionne, obtenez uniquement l'adresse dans la méthode StartAsync, pas dans le constructeur du service!

    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;
        }
    }
1
Maxim T