Usar assemblies de inicialização de hospedagem no ASP.NET Core

Por Pavel Krymets

Uma implementação IHostingStartup (inicialização de hospedagem) adiciona melhorias a um aplicativo durante a inicialização de um assembly externo. Por exemplo, uma biblioteca externa pode usar uma implementação de inicialização de hospedagem para fornecer serviços ou provedores de configuração adicionais a um aplicativo.

Exibir ou baixar código de exemplo (como baixar)

Atributo HostingStartup

Um atributo HostingStartup indica a presença de um assembly de inicialização de hospedagem para ativar em runtime.

O assembly de entrada ou o assembly que contém a classe Startup é automaticamente examinado para o atributo HostingStartup. A lista de assemblies a ser pesquisada para os atributos HostingStartup é carregada no runtime da configuração em WebHostDefaults.HostingStartupAssembliesKey. A lista de assemblies para excluir da descoberta é carregada de WebHostDefaults.HostingStartupExcludeAssembliesKey.

No exemplo a seguir, o namespace do assembly de inicialização de hospedagem é StartupEnhancement. A classe que contém o código de inicialização de hospedagem é StartupEnhancementHostingStartup:

[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]

O atributo HostingStartup normalmente está localizado no arquivo de classe de implementação IHostingStartup do assembly de inicialização de hospedagem.

Descobrir assemblies de inicialização de hospedagem carregados

Para descobrir os assemblies de inicialização de hospedagem carregados, habilite o registro em log e verifique os logs do aplicativo. Erros que ocorrem quando os assemblies carregados são registrados em log. Os assemblies de inicialização de hospedagem carregados são registrados em log no nível Depuração e todos os erros são registrados.

Desabilitar o carregamento automático de assemblies de inicialização de hospedagem

Para desabilitar o carregamento automático de assemblies de inicialização de hospedagem, use uma das seguintes abordagens:

  • Para impedir o carregamento de todos os assemblies de inicialização de hospedagem, defina o seguinte para true ou 1:

    • Definição de configuração do host Impedir inicialização de hospedagem:

      public static IHostBuilder CreateHostBuilder(string[] args) =>
          Host.CreateDefaultBuilder(args)
              .ConfigureWebHostDefaults(webBuilder =>
              {
                  webBuilder.UseSetting(
                          WebHostDefaults.PreventHostingStartupKey, "true")
                      .UseStartup<Startup>();
              });
      
    • A variável de ambiente ASPNETCORE_PREVENTHOSTINGSTARTUP.

  • Para evitar o carregamento de assemblies específicos de inicialização de hospedagem, defina uma das opções a seguir como uma cadeia de caracteres delimitada por ponto e vírgula de assemblies de inicialização de hospedagem para excluir na inicialização:

    • Definição de configuração do host Assemblies de exclusão da inicialização de hospedagem:

      public static IHostBuilder CreateHostBuilder(string[] args) =>
          Host.CreateDefaultBuilder(args)
              .ConfigureWebHostDefaults(webBuilder =>
              {
                  webBuilder.UseSetting(
                          WebHostDefaults.HostingStartupExcludeAssembliesKey, 
                          "{ASSEMBLY1;ASSEMBLY2; ...}")
                      .UseStartup<Startup>();
              });
      

      O espaço reservado {ASSEMBLY1;ASSEMBLY2; ...} representa a lista de assemblies separados por ponto e vírgula.

    • A variável de ambiente ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES.

Se a configuração do host e a variável de ambiente estiverem definidas, a configuração do host controlará o comportamento.

A desabilitação de assemblies de inicialização de hospedagem usando a configuração do host ou a variável de ambiente desabilita o assembly globalmente e poderá desabilitar várias características de um aplicativo.

Project

Crie uma inicialização de hospedagem com qualquer um dos seguintes tipos de projeto:

Biblioteca de classes

Uma melhoria da inicialização de hospedagem pode ser fornecida em uma biblioteca de classes. A biblioteca contém um atributo HostingStartup.

O código de exemplo inclui um aplicativo Páginas do Razor, HostingStartupApp e uma biblioteca de classes, HostingStartupLibrary. A biblioteca de classes:

  • Contém uma classe de inicialização de hospedagem, ServiceKeyInjection, que implementa IHostingStartup. ServiceKeyInjection adiciona um par de cadeias de caracteres de serviço à configuração do aplicativo usando o provedor de configuração na memória (AddInMemoryCollection).
  • Inclui um atributo HostingStartup que identifica o namespace e a classe de inicialização de hospedagem.

O método Configure da classe ServiceKeyInjection usa um IWebHostBuilder para adicionar aprimoramentos a um aplicativo.

HostingStartupLibrary/ServiceKeyInjection.cs:

[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]

namespace HostingStartupLibrary
{
    public class ServiceKeyInjection : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureAppConfiguration(config =>
            {
                var dict = new Dictionary<string, string>
                {
                    {"DevAccount_FromLibrary", "DEV_1111111-1111"},
                    {"ProdAccount_FromLibrary", "PROD_2222222-2222"}
                };

                config.AddInMemoryCollection(dict);
            });
        }
    }
}

A página de índice do aplicativo lê e renderiza os valores de configuração para as duas chaves definidas pelo assembly de inicialização de hospedagem da biblioteca de classes:

HostingStartupApp/Pages/Index.cshtml.cs:

public class IndexModel : PageModel
{
    public IndexModel(IConfiguration config)
    {
        ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
        ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
        ServiceKey_Development_Package = config["DevAccount_FromPackage"];
        ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
    }

    public string ServiceKey_Development_Library { get; private set; }
    public string ServiceKey_Production_Library { get; private set; }
    public string ServiceKey_Development_Package { get; private set; }
    public string ServiceKey_Production_Package { get; private set; }

    public void OnGet()
    {
    }
}

O código de exemplo também inclui um projeto de pacote do NuGet que fornece uma inicialização de hospedagem separada, HostingStartupPackage. O pacote tem as mesmas características da biblioteca de classes descrita anteriormente. O pacote:

  • Contém uma classe de inicialização de hospedagem, ServiceKeyInjection, que implementa IHostingStartup. ServiceKeyInjection adiciona um par de cadeias de caracteres de serviço para a configuração do aplicativo.
  • Inclui um atributo HostingStartup.

HostingStartupPackage/ServiceKeyInjection.cs:

[assembly: HostingStartup(typeof(HostingStartupPackage.ServiceKeyInjection))]

namespace HostingStartupPackage
{
    public class ServiceKeyInjection : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureAppConfiguration(config =>
            {
                var dict = new Dictionary<string, string>
                {
                    {"DevAccount_FromPackage", "DEV_3333333-3333"},
                    {"ProdAccount_FromPackage", "PROD_4444444-4444"}
                };

                config.AddInMemoryCollection(dict);
            });
        }
    }
}

A página de índice do aplicativo lê e renderiza os valores de configuração para as duas chaves definidas pelo assembly de inicialização de hospedagem do pacote:

HostingStartupApp/Pages/Index.cshtml.cs:

public class IndexModel : PageModel
{
    public IndexModel(IConfiguration config)
    {
        ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
        ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
        ServiceKey_Development_Package = config["DevAccount_FromPackage"];
        ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
    }

    public string ServiceKey_Development_Library { get; private set; }
    public string ServiceKey_Production_Library { get; private set; }
    public string ServiceKey_Development_Package { get; private set; }
    public string ServiceKey_Production_Package { get; private set; }

    public void OnGet()
    {
    }
}

Aplicativo de console sem um ponto de entrada

Essa abordagem só está disponível para aplicativos .NET Core, não para .NET Framework.

Uma melhoria de inicialização de hospedagem dinâmica que não requer uma referência de tempo de compilação para a ativação pode ser fornecida em um aplicativo de console sem um ponto de entrada que contenha um atributo HostingStartup. Publicar o aplicativo de console produz um assembly de inicialização de hospedagem que pode ser consumido do repositório de runtime.

Um aplicativo de console sem um ponto de entrada é usado nesse processo porque:

  • Um arquivo de dependências é necessário para consumir a inicialização de hospedagem no assembly de inicialização de hospedagem. Um arquivo de dependências é um ativo de aplicativo executável que é produzido ao publicar um aplicativo, não uma biblioteca.
  • Uma biblioteca não pode ser adicionada diretamente ao repositório de pacotes de runtime, o que exige um projeto executável que tem como alvo o runtime compartilhado.

Na criação de uma inicialização de hospedagem dinâmica:

  • Um assembly de inicialização de hospedagem é criado no aplicativo de console sem um ponto de entrada que:
    • Inclui uma classe que contém a implementação de IHostingStartup.
    • Inclui um atributo HostingStartup para identificar a classe de implementação de IHostingStartup.
  • O aplicativo de console é publicado para obter as dependências da inicialização de hospedagem. Uma consequência de publicar o aplicativo de console é que as dependências não utilizadas são cortadas do arquivo de dependências.
  • O arquivo de dependências é modificado para definir o local de runtime do assembly de inicialização de hospedagem.
  • O assembly de inicialização de hospedagem e seu arquivo de dependências são colocados no repositório do pacote de runtime. Para descobrir o assembly de inicialização de hospedagem e seu arquivo de dependências, eles são listados em um par de variáveis de ambiente.

O assembly de aplicativo do console referencia o pacote Microsoft.AspNetCore.Hosting.Abstractions:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" 
                      Version="3.0.0" />
  </ItemGroup>

</Project>

Um atributo HostingStartup identifica uma classe como uma implementação de IHostingStartup para o carregamento e a execução durante a compilação do IWebHost. No seguinte exemplo, o namespace é StartupEnhancement e a classe é StartupEnhancementHostingStartup:

[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]

Uma classe implementa IHostingStartup. O método Configure da classe usa um IWebHostBuilder para adicionar aprimoramentos a um aplicativo. IHostingStartup.Configure no assembly de inicialização de hospedagem é chamado pelo runtime antes de Startup.Configure no código do usuário, o que permite que o código de usuário substitua qualquer configuração fornecida pelo assembly de inicialização de hospedagem.

namespace StartupEnhancement
{
    public class StartupEnhancementHostingStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            // Use the IWebHostBuilder to add app enhancements.
        }
    }
}

Ao compilar um projeto IHostingStartup, o arquivo de dependências (.deps.json) define o local runtime do assembly como a pasta bin:

"targets": {
  ".NETCoreApp,Version=v3.0": {
    "StartupEnhancement/1.0.0": {
      "dependencies": {
        "Microsoft.AspNetCore.Hosting.Abstractions": "3.0.0"
      },
      "runtime": {
        "StartupEnhancement.dll": {}
      }
    }
  }
}

Apenas uma parte do arquivo é mostrada. O nome do assembly no exemplo é StartupEnhancement.

Configuração fornecida pela inicialização da hospedagem

Existem duas abordagens para lidar com a configuração, dependendo se você deseja que a configuração da inicialização da hospedagem tenha precedência ou que a configuração do aplicativo tenha precedência:

  1. Configure o aplicativo usando ConfigureAppConfiguration para carregar a configuração depois que os representantes ConfigureAppConfiguration do aplicativo forem executados. A configuração de inicialização de hospedagem tem prioridade sobre a configuração do aplicativo que usa essa abordagem.
  2. Configure o aplicativo usando UseConfiguration para carregar a configuração antes que os representantes ConfigureAppConfiguration do aplicativo sejam executados. Os valores de configuração do aplicativo têm prioridade sobre aqueles fornecidos pela inicialização da hospedagem que usa essa abordagem.
public class ConfigurationInjection : IHostingStartup
{
    public void Configure(IWebHostBuilder builder)
    {
        Dictionary<string, string> dict;

        builder.ConfigureAppConfiguration(config =>
        {
            dict = new Dictionary<string, string>
            {
                {"ConfigurationKey1", 
                    "From IHostingStartup: Higher priority " +
                    "than the app's configuration."},
            };

            config.AddInMemoryCollection(dict);
        });

        dict = new Dictionary<string, string>
        {
            {"ConfigurationKey2", 
                "From IHostingStartup: Lower priority " +
                "than the app's configuration."},
        };

        var builtConfig = new ConfigurationBuilder()
            .AddInMemoryCollection(dict)
            .Build();

        builder.UseConfiguration(builtConfig);
    }
}

Especificar o assembly de inicialização de hospedagem

Para uma biblioteca de classes ou inicialização de hospedagem fornecida pelo aplicativo de console, especifique o nome do assembly de inicialização de hospedagem na variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES. A variável de ambiente é uma lista de assemblies delimitada por ponto e vírgula.

Apenas assemblies de inicialização de hospedagem são examinados quanto ao atributo HostingStartup. Para o aplicativo de exemplo, HostingStartupApp, para descobrir as inicializações de hospedagem descritas anteriormente, a variável de ambiente é definida como o seguinte valor:

HostingStartupLibrary;HostingStartupPackage;StartupDiagnostics

Um assembly de inicialização de hospedagem também pode ser definido usando a definição de configuração do host Assemblies de inicialização de hospedagem:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseSetting(
                    WebHostDefaults.HostingStartupAssembliesKey, 
                    "{ASSEMBLY1;ASSEMBLY2; ...}")
                .UseStartup<Startup>();
        });

O espaço reservado {ASSEMBLY1;ASSEMBLY2; ...} representa a lista de assemblies separados por ponto e vírgula.

Quando há vários assemblies de inicialização de hospedagem, os métodos Configure são executados na ordem em que os assemblies são listados.

Ativação

As opções para ativação da inicialização de hospedagem são:

  • Repositório de runtime: a ativação não requer uma referência de tempo de compilação para a ativação. O aplicativo de exemplo coloca os arquivos de dependências e o assembly de inicialização de hospedagem em uma pasta, implantação, para facilitar a implantação da inicialização de hospedagem em um ambiente multicomputador. A pasta implantação também inclui um script do PowerShell que cria ou modifica variáveis de ambiente no sistema de implantação para habilitar a inicialização de hospedagem.
  • Referência de tempo de compilação necessária para a ativação

Repositório de runtime

A implementação de inicialização de hospedagem é colocada no repositório de runtime. Uma referência de tempo de compilação para o assembly não é exigida pelo aplicativo aprimorado.

Depois que a inicialização de hospedagem é compilada, um repositório de runtime é gerado, usando o arquivo de projeto do manifesto e o comando do dotnet store.

dotnet store --manifest {MANIFEST FILE} --runtime {RUNTIME IDENTIFIER} --output {OUTPUT LOCATION} --skip-optimization

No aplicativo de exemplo (projeto RuntimeStore) é usado o seguinte comando:

dotnet store --manifest store.manifest.csproj --runtime win7-x64 --output ./deployment/store --skip-optimization

Para o runtime descobrir o repositório de runtime, o local do repositório de runtime é adicionado à variável de ambiente DOTNET_SHARED_STORE.

Modificar e colocar o arquivo de dependências da inicialização de hospedagem

Para ativar o aprimoramento sem uma referência de pacote ao aprimoramento, especifique as dependências adicionais do runtime com additionalDeps. additionalDeps permite que você:

  • Estenda o grafo de biblioteca do aplicativo fornecendo um conjunto de arquivos .deps.json adicionais a serem mesclados com o próprio arquivo .deps.json do aplicativo na inicialização.
  • Torne o assembly de inicialização de hospedagem detectável e carregável.

A abordagem recomendada para gerar o arquivo de dependências adicionais é:

  1. Executar o dotnet publish no arquivo de manifesto do repositório de runtime mencionado na seção anterior.
  2. Remover a referência do manifesto das bibliotecas e a seção runtime do arquivo .deps.json resultante.

No projeto de exemplo, a propriedade store.manifest/1.0.0 é removida das seções targets e libraries:

{
  "runtimeTarget": {
    "name": ".NETCoreApp,Version=v3.0",
    "signature": ""
  },
  "compilationOptions": {},
  "targets": {
    ".NETCoreApp,Version=v3.0": {
      "store.manifest/1.0.0": {
        "dependencies": {
          "StartupDiagnostics": "1.0.0"
        },
        "runtime": {
          "store.manifest.dll": {}
        }
      },
      "StartupDiagnostics/1.0.0": {
        "runtime": {
          "lib/netcoreapp3.0/StartupDiagnostics.dll": {
            "assemblyVersion": "1.0.0.0",
            "fileVersion": "1.0.0.0"
          }
        }
      }
    }
  },
  "libraries": {
    "store.manifest/1.0.0": {
      "type": "project",
      "serviceable": false,
      "sha512": ""
    },
    "StartupDiagnostics/1.0.0": {
      "type": "package",
      "serviceable": true,
      "sha512": "sha512-xrhzuNSyM5/f4ZswhooJ9dmIYLP64wMnqUJSyTKVDKDVj5T+qtzypl8JmM/aFJLLpYrf0FYpVWvGujd7/FfMEw==",
      "path": "startupdiagnostics/1.0.0",
      "hashPath": "startupdiagnostics.1.0.0.nupkg.sha512"
    }
  }
}

Coloque o arquivo .deps.json no seguinte local:

{ADDITIONAL DEPENDENCIES PATH}/shared/{SHARED FRAMEWORK NAME}/{SHARED FRAMEWORK VERSION}/{ENHANCEMENT ASSEMBLY NAME}.deps.json
  • {ADDITIONAL DEPENDENCIES PATH}: local adicionado à variável de ambiente DOTNET_ADDITIONAL_DEPS.
  • {SHARED FRAMEWORK NAME}: estrutura compartilhada necessária para esse arquivo de dependências adicionais.
  • {SHARED FRAMEWORK VERSION}: versão mínima de estrutura compartilhada.
  • {ENHANCEMENT ASSEMBLY NAME}: nome do assembly do aprimoramento.

No aplicativo de exemplo (projeto RuntimeStore), o arquivo de dependências adicionais é colocado no seguinte local:

deployment/additionalDeps/shared/Microsoft.AspNetCore.App/3.0.0/StartupDiagnostics.deps.json

Para o runtime descobrir o local do repositório de runtime, o local do arquivo de dependências adicionais é adicionado à variável de ambiente DOTNET_ADDITIONAL_DEPS.

No aplicativo de exemplo (projeto RuntimeStore), crie o repositório de tempo de execução e gere o arquivo de dependências adicionais usando um script PowerShell.

Para obter exemplos de como definir variáveis de ambiente para vários sistemas operacionais, confira Usar vários ambientes.

Implantação

Para facilitar a implantação de uma inicialização de hospedagem em um ambiente multicomputador, o aplicativo de exemplo cria uma pasta implantação na saída publicada que contém:

  • O repositório de runtime de inicialização de hospedagem.
  • O arquivo de dependências de inicialização de hospedagem.
  • Um script do PowerShell que cria ou modifica ASPNETCORE_HOSTINGSTARTUPASSEMBLIES, DOTNET_SHARED_STORE e DOTNET_ADDITIONAL_DEPS para dar suporte à ativação da inicialização de hospedagem. Execute o script de um prompt de comando do PowerShell administrativo no sistema de implantação.

Pacote NuGet

Uma melhoria da inicialização de hospedagem pode ser fornecida em pacote do NuGet. O pacote tem um atributo HostingStartup. Os tipos de inicialização de hospedagem fornecidos pelo pacote são disponibilizados para o aplicativo usando qualquer uma das seguintes abordagens:

  • O arquivo de projeto do aplicativo aprimorado faz uma referência de pacote para a inicialização de hospedagem no arquivo de projeto do aplicativo (uma referência de tempo de compilação). Com a referência de tempo de compilação em vigor, o assembly de inicialização de hospedagem e todas as suas dependências são incorporados ao arquivo de dependência do aplicativo (.deps.json). Essa abordagem se aplica a um pacote de assembly de inicialização de hospedagem publicado para nuget.org.
  • O arquivo de dependências da inicialização de hospedagem fica disponível para o aplicativo avançado, conforme descrito na seção Repositório de runtime (sem uma referência de tempo de compilação).

Para obter mais informações sobre pacotes do NuGet e o repositório de runtime, consulte os tópicos a seguir:

Pasta Lixeira do projeto

Uma melhoria da inicialização de hospedagem pode ser fornecida por um assemby implantado na lixeira no aplicativo aprimorado. Os tipos de inicialização de hospedagem fornecidos pelo assembly são disponibilizados para o aplicativo usando uma das seguintes abordagens:

  • O arquivo de projeto do aplicativo aprimorado faz uma referência de assembly para a inicialização de hospedagem (uma referência de tempo de compilação). Com a referência de tempo de compilação em vigor, o assembly de inicialização de hospedagem e todas as suas dependências são incorporados ao arquivo de dependência do aplicativo (.deps.json). Essa abordagem se aplica quando o cenário de implantação demanda fazer uma referência de tempo de compilação ao assembly da inicialização de hospedagem (arquivo .dll) e mover o assembly para:
    • o projeto de consumo.
    • um local acessível ao projeto de consumo.
  • O arquivo de dependências da inicialização de hospedagem fica disponível para o aplicativo avançado, conforme descrito na seção Repositório de runtime (sem uma referência de tempo de compilação).
  • Ao ter como destino o .NET Framework, o assembly é carregável no contexto de carga padrão, o que, no .NET Framework, significa que ele fica em um dos seguintes locais:
    • Caminho da base de aplicativo: a pasta bin onde o executável do aplicativo(.exe) está localizado.
    • Cache de assembly global (GAC, na sigla em inglês): o GAC armazena assemblies que vários aplicativos .NET Framework compartilham. Para obter mais informações, consulte Instalação de um assembly no cache de assembly global na documentação do .NET Framework.

Código de exemplo

O código de exemplo (como baixar) demonstra cenários de implementação de inicialização de hospedagem:

  • Dois assemblies de inicialização de hospedagem (bibliotecas de classes) definem um par chave-valor de configuração na memória cada:
    • Pacote do NuGet (HostingStartupPackage)
    • Biblioteca de classes (HostingStartupLibrary)
  • Uma inicialização de hospedagem é ativada de um assembly implantado pelo repositório de runtime (StartupDiagnostics). O assembly adiciona dois middlewares ao aplicativo na inicialização que fornecem informações de diagnóstico sobre:
    • Serviços registrados
    • Endereço (esquema, host, base do caminho, caminho, cadeia de caracteres de consulta)
    • Conexão (IP remoto, porta remota, IP local, porta local, certificado do cliente)
    • Cabeçalhos da solicitação
    • Variáveis de ambiente

Para executar o exemplo:

Ativação de um pacote do NuGet

  1. Compile o pacote HostingStartupPackage com o comando dotnet pack.

  2. Adicione o nome do assembly do pacote do HostingStartupPackage para a variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES.

  3. Compile e execute o aplicativo. Uma referência de pacote está presente no aplicativo aprimorado (uma referência de tempo de compilação). Um <PropertyGroup> no arquivo de projeto do aplicativo especifica a saída do projeto de pacote (../HostingStartupPackage/bin/Debug) como uma origem de pacote. Isso permite que o aplicativo use o pacote sem carregar o pacote no nuget.org. Para obter mais informações, consulte as anotações no arquivo de projeto do HostingStartupApp.

    <PropertyGroup>
      <RestoreSources>$(RestoreSources);https://api.nuget.org/v3/index.json;../HostingStartupPackage/bin/Debug</RestoreSources>
    </PropertyGroup>
    
  4. Observe que os valores de chave de configuração do serviço renderizados pela página de índice correspondem aos valores definidos pelo método ServiceKeyInjection.Configure do pacote.

Se você fizer alterações no projeto HostingStartupPackage e recompilá-lo, limpe os caches de pacote do NuGet locais para garantir que o HostingStartupApp receba o pacote atualizado e não um pacote obsoleto do cache local. Para limpar os caches locais do NuGet, execute o seguinte comando dotnet nuget locals:

dotnet nuget locals all --clear

Ativação de uma biblioteca de classes

  1. Compile a biblioteca de classes HostingStartupLibrary com o comando dotnet build.

  2. Adicione nome do assembly da biblioteca de classes do HostingStartupLibrary à variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES.

  3. A pasta lixeira implanta o assembly da biblioteca de classes para o aplicativo ao copiar o arquivo HostingStartupLibrary.dll da saída compilada da biblioteca de classes para a pasta lixeira/Depurar do aplicativo.

  4. Compile e execute o aplicativo. Um <ItemGroup> no arquivo de projeto do aplicativo referencia o assembly da biblioteca de classes (.\bin\Debug\netcoreapp3.0\HostingStartupLibrary.dll) (uma referência de tempo de compilação). Para mais informações, consulte as notas no arquivo de projeto do HostingStartupApp.

    <ItemGroup>
      <Reference Include=".\\bin\\Debug\\netcoreapp3.0\\HostingStartupLibrary.dll">
        <HintPath>.\bin\Debug\netcoreapp3.0\HostingStartupLibrary.dll</HintPath>
        <SpecificVersion>False</SpecificVersion> 
      </Reference>
    </ItemGroup>
    
  5. Observe que os valores de chave de configuração do serviço renderizados pela página de índice correspondem aos valores definidos pelo método ServiceKeyInjection.Configure da biblioteca de classes.

Ativação de um assembly implantado pelo repositório de runtime

  1. O projeto StartupDiagnostics usa o PowerShell para modificar seu arquivo StartupDiagnostics.deps.json. O PowerShell é instalado por padrão em um sistema operacional Windows começando no Windows 7 SP1 e no Windows Server 2008 R2 SP1. Para obter o PowerShell em outras plataformas, consulte Instalando várias versões do PowerShell.
  2. Execute o script build.ps1 na pasta RuntimeStore. O script:
    • Gera o pacote StartupDiagnostics na pasta obj\packages.
    • Gera o repositório de runtime para StartupDiagnostics na pasta de armazenamento. O comando dotnet store no script usa o win7-x64RID (identificador de runtime) para uma inicialização de host implantada no Windows. Ao fornecer a inicialização de hospedagem para um runtime diferente, substitua pelo RID correto na linha 37 do script. O repositório de runtime para StartupDiagnostics posteriormente seria movido para o repositório de runtime do usuário ou do sistema no computador em que o assembly será consumido. O local de instalação do repositório de runtime do usuário para o assembly StartupDiagnostics é .dotnet/store/x64/netcoreapp3.0/startupdiagnostics/1.0.0/lib/netcoreapp3.0/StartupDiagnostics.dll.
    • Gera o additionalDeps para StartupDiagnostics na pasta additionalDeps. As dependências adicionais posteriormente seriam movidas para as dependências adicionais do usuário ou do sistema. O local de instalação de dependências adicionais do usuário StartupDiagnostics é .dotnet/x64/additionalDeps/StartupDiagnostics/shared/Microsoft.NETCore.App/3.0.0/StartupDiagnostics.deps.json.
    • Coloca o arquivo deploy.ps1 na pasta deployment.
  3. Execute o script deploy.ps1 na pasta deployment. O script acrescenta:
    • StartupDiagnostics à variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES.
    • O caminho de dependências de inicialização de hospedagem (na pasta de implantação do projeto RuntimeStore) para a variável de ambiente DOTNET_ADDITIONAL_DEPS.
    • O caminho do repositório de runtime (na pasta de implantação do projeto RuntimeStore) para a variável de ambiente DOTNET_SHARED_STORE.
  4. Execute o aplicativo de exemplo.
  5. Solicite o ponto de extremidade /services para ver os serviços registrados do aplicativo. Solicite o ponto de extremidade /diag para ver as informações de diagnóstico.

Uma implementação IHostingStartup (inicialização de hospedagem) adiciona melhorias a um aplicativo durante a inicialização de um assembly externo. Por exemplo, uma biblioteca externa pode usar uma implementação de inicialização de hospedagem para fornecer serviços ou provedores de configuração adicionais a um aplicativo.

Exibir ou baixar código de exemplo (como baixar)

Atributo HostingStartup

Um atributo HostingStartup indica a presença de um assembly de inicialização de hospedagem para ativar em runtime.

O assembly de entrada ou o assembly que contém a classe Startup é automaticamente examinado para o atributo HostingStartup. A lista de assemblies a ser pesquisada para os atributos HostingStartup é carregada no runtime da configuração em WebHostDefaults.HostingStartupAssembliesKey. A lista de assemblies para excluir da descoberta é carregada de WebHostDefaults.HostingStartupExcludeAssembliesKey. Para obter mais informações, consulte Host da Web: assemblies de inicialização de hospedagem e Host da Web: assemblies de exclusão da inicialização de hospedagem.

No exemplo a seguir, o namespace do assembly de inicialização de hospedagem é StartupEnhancement. A classe que contém o código de inicialização de hospedagem é StartupEnhancementHostingStartup:

[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]

O atributo HostingStartup normalmente está localizado no arquivo de classe de implementação IHostingStartup do assembly de inicialização de hospedagem.

Descobrir assemblies de inicialização de hospedagem carregados

Para descobrir os assemblies de inicialização de hospedagem carregados, habilite o registro em log e verifique os logs do aplicativo. Erros que ocorrem quando os assemblies carregados são registrados em log. Os assemblies de inicialização de hospedagem carregados são registrados em log no nível Depuração e todos os erros são registrados.

Desabilitar o carregamento automático de assemblies de inicialização de hospedagem

Para desabilitar o carregamento automático de assemblies de inicialização de hospedagem, use uma das seguintes abordagens:

  • Para impedir o carregamento de todos os assemblies de inicialização de hospedagem, defina o seguinte para true ou 1:
  • Para evitar o carregamento de assemblies específicos de inicialização de hospedagem, defina uma das opções a seguir como uma cadeia de caracteres delimitada por ponto e vírgula de assemblies de inicialização de hospedagem para excluir na inicialização:

Se a configuração do host e a variável de ambiente estiverem definidas, a configuração do host controlará o comportamento.

A desabilitação de assemblies de inicialização de hospedagem usando a configuração do host ou a variável de ambiente desabilita o assembly globalmente e poderá desabilitar várias características de um aplicativo.

Project

Crie uma inicialização de hospedagem com qualquer um dos seguintes tipos de projeto:

Biblioteca de classes

Uma melhoria da inicialização de hospedagem pode ser fornecida em uma biblioteca de classes. A biblioteca contém um atributo HostingStartup.

O código de exemplo inclui um aplicativo Páginas do Razor, HostingStartupApp e uma biblioteca de classes, HostingStartupLibrary. A biblioteca de classes:

  • Contém uma classe de inicialização de hospedagem, ServiceKeyInjection, que implementa IHostingStartup. ServiceKeyInjection adiciona um par de cadeias de caracteres de serviço à configuração do aplicativo usando o provedor de configuração na memória (AddInMemoryCollection).
  • Inclui um atributo HostingStartup que identifica o namespace e a classe de inicialização de hospedagem.

O método Configure da classe ServiceKeyInjection usa um IWebHostBuilder para adicionar aprimoramentos a um aplicativo.

HostingStartupLibrary/ServiceKeyInjection.cs:

[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]

namespace HostingStartupLibrary
{
    public class ServiceKeyInjection : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureAppConfiguration(config =>
            {
                var dict = new Dictionary<string, string>
                {
                    {"DevAccount_FromLibrary", "DEV_1111111-1111"},
                    {"ProdAccount_FromLibrary", "PROD_2222222-2222"}
                };

                config.AddInMemoryCollection(dict);
            });
        }
    }
}

A página de índice do aplicativo lê e renderiza os valores de configuração para as duas chaves definidas pelo assembly de inicialização de hospedagem da biblioteca de classes:

HostingStartupApp/Pages/Index.cshtml.cs:

public class IndexModel : PageModel
{
    public IndexModel(IConfiguration config)
    {
        ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
        ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
        ServiceKey_Development_Package = config["DevAccount_FromPackage"];
        ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
    }

    public string ServiceKey_Development_Library { get; private set; }
    public string ServiceKey_Production_Library { get; private set; }
    public string ServiceKey_Development_Package { get; private set; }
    public string ServiceKey_Production_Package { get; private set; }

    public void OnGet()
    {
    }
}

O código de exemplo também inclui um projeto de pacote do NuGet que fornece uma inicialização de hospedagem separada, HostingStartupPackage. O pacote tem as mesmas características da biblioteca de classes descrita anteriormente. O pacote:

  • Contém uma classe de inicialização de hospedagem, ServiceKeyInjection, que implementa IHostingStartup. ServiceKeyInjection adiciona um par de cadeias de caracteres de serviço para a configuração do aplicativo.
  • Inclui um atributo HostingStartup.

HostingStartupPackage/ServiceKeyInjection.cs:

[assembly: HostingStartup(typeof(HostingStartupPackage.ServiceKeyInjection))]

namespace HostingStartupPackage
{
    public class ServiceKeyInjection : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureAppConfiguration(config =>
            {
                var dict = new Dictionary<string, string>
                {
                    {"DevAccount_FromPackage", "DEV_3333333-3333"},
                    {"ProdAccount_FromPackage", "PROD_4444444-4444"}
                };

                config.AddInMemoryCollection(dict);
            });
        }
    }
}

A página de índice do aplicativo lê e renderiza os valores de configuração para as duas chaves definidas pelo assembly de inicialização de hospedagem do pacote:

HostingStartupApp/Pages/Index.cshtml.cs:

public class IndexModel : PageModel
{
    public IndexModel(IConfiguration config)
    {
        ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
        ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
        ServiceKey_Development_Package = config["DevAccount_FromPackage"];
        ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
    }

    public string ServiceKey_Development_Library { get; private set; }
    public string ServiceKey_Production_Library { get; private set; }
    public string ServiceKey_Development_Package { get; private set; }
    public string ServiceKey_Production_Package { get; private set; }

    public void OnGet()
    {
    }
}

Aplicativo de console sem um ponto de entrada

Essa abordagem só está disponível para aplicativos .NET Core, não para .NET Framework.

Uma melhoria de inicialização de hospedagem dinâmica que não requer uma referência de tempo de compilação para a ativação pode ser fornecida em um aplicativo de console sem um ponto de entrada que contenha um atributo HostingStartup. Publicar o aplicativo de console produz um assembly de inicialização de hospedagem que pode ser consumido do repositório de runtime.

Um aplicativo de console sem um ponto de entrada é usado nesse processo porque:

  • Um arquivo de dependências é necessário para consumir a inicialização de hospedagem no assembly de inicialização de hospedagem. Um arquivo de dependências é um ativo de aplicativo executável que é produzido ao publicar um aplicativo, não uma biblioteca.
  • Uma biblioteca não pode ser adicionada diretamente ao repositório de pacotes de runtime, o que exige um projeto executável que tem como alvo o runtime compartilhado.

Na criação de uma inicialização de hospedagem dinâmica:

  • Um assembly de inicialização de hospedagem é criado no aplicativo de console sem um ponto de entrada que:
    • Inclui uma classe que contém a implementação de IHostingStartup.
    • Inclui um atributo HostingStartup para identificar a classe de implementação de IHostingStartup.
  • O aplicativo de console é publicado para obter as dependências da inicialização de hospedagem. Uma consequência de publicar o aplicativo de console é que as dependências não utilizadas são cortadas do arquivo de dependências.
  • O arquivo de dependências é modificado para definir o local de runtime do assembly de inicialização de hospedagem.
  • O assembly de inicialização de hospedagem e seu arquivo de dependências são colocados no repositório do pacote de runtime. Para descobrir o assembly de inicialização de hospedagem e seu arquivo de dependências, eles são listados em um par de variáveis de ambiente.

O assembly de aplicativo do console referencia o pacote Microsoft.AspNetCore.Hosting.Abstractions:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" 
                      Version="2.1.1" />
  </ItemGroup>

</Project>

Um atributo HostingStartup identifica uma classe como uma implementação de IHostingStartup para o carregamento e a execução durante a compilação do IWebHost. No seguinte exemplo, o namespace é StartupEnhancement e a classe é StartupEnhancementHostingStartup:

[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]

Uma classe implementa IHostingStartup. O método Configure da classe usa um IWebHostBuilder para adicionar aprimoramentos a um aplicativo. IHostingStartup.Configure no assembly de inicialização de hospedagem é chamado pelo runtime antes de Startup.Configure no código do usuário, o que permite que o código de usuário substitua qualquer configuração fornecida pelo assembly de inicialização de hospedagem.

namespace StartupEnhancement
{
    public class StartupEnhancementHostingStartup : IHostingStartup
    {
        public void Configure(IWebHostBuilder builder)
        {
            // Use the IWebHostBuilder to add app enhancements.
        }
    }
}

Ao compilar um projeto IHostingStartup, o arquivo de dependências (.deps.json) define o local runtime do assembly como a pasta bin:

"targets": {
  ".NETCoreApp,Version=v2.1": {
    "StartupEnhancement/1.0.0": {
      "dependencies": {
        "Microsoft.AspNetCore.Hosting.Abstractions": "2.1.1"
      },
      "runtime": {
        "StartupEnhancement.dll": {}
      }
    }
  }
}

Apenas uma parte do arquivo é mostrada. O nome do assembly no exemplo é StartupEnhancement.

Configuração fornecida pela inicialização da hospedagem

Existem duas abordagens para lidar com a configuração, dependendo se você deseja que a configuração da inicialização da hospedagem tenha precedência ou que a configuração do aplicativo tenha precedência:

  1. Configure o aplicativo usando ConfigureAppConfiguration para carregar a configuração depois que os representantes ConfigureAppConfiguration do aplicativo forem executados. A configuração de inicialização de hospedagem tem prioridade sobre a configuração do aplicativo que usa essa abordagem.
  2. Configure o aplicativo usando UseConfiguration para carregar a configuração antes que os representantes ConfigureAppConfiguration do aplicativo sejam executados. Os valores de configuração do aplicativo têm prioridade sobre aqueles fornecidos pela inicialização da hospedagem que usa essa abordagem.
public class ConfigurationInjection : IHostingStartup
{
    public void Configure(IWebHostBuilder builder)
    {
        Dictionary<string, string> dict;

        builder.ConfigureAppConfiguration(config =>
        {
            dict = new Dictionary<string, string>
            {
                {"ConfigurationKey1", 
                    "From IHostingStartup: Higher priority " +
                    "than the app's configuration."},
            };

            config.AddInMemoryCollection(dict);
        });

        dict = new Dictionary<string, string>
        {
            {"ConfigurationKey2", 
                "From IHostingStartup: Lower priority " +
                "than the app's configuration."},
        };

        var builtConfig = new ConfigurationBuilder()
            .AddInMemoryCollection(dict)
            .Build();

        builder.UseConfiguration(builtConfig);
    }
}

Especificar o assembly de inicialização de hospedagem

Para uma biblioteca de classes ou inicialização de hospedagem fornecida pelo aplicativo de console, especifique o nome do assembly de inicialização de hospedagem na variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES. A variável de ambiente é uma lista de assemblies delimitada por ponto e vírgula.

Apenas assemblies de inicialização de hospedagem são examinados quanto ao atributo HostingStartup. Para o aplicativo de exemplo, HostingStartupApp, para descobrir as inicializações de hospedagem descritas anteriormente, a variável de ambiente é definida como o seguinte valor:

HostingStartupLibrary;HostingStartupPackage;StartupDiagnostics

Um assembly de inicialização de hospedagem também pode ser definido usando a configuração do host Assemblies de inicialização de hospedagem.

Quando há vários assemblies de inicialização de hospedagem, os métodos Configure são executados na ordem em que os assemblies são listados.

Ativação

As opções para ativação da inicialização de hospedagem são:

  • Repositório de runtime: a ativação não requer uma referência de tempo de compilação para a ativação. O aplicativo de exemplo coloca os arquivos de dependências e o assembly de inicialização de hospedagem em uma pasta, implantação, para facilitar a implantação da inicialização de hospedagem em um ambiente multicomputador. A pasta implantação também inclui um script do PowerShell que cria ou modifica variáveis de ambiente no sistema de implantação para habilitar a inicialização de hospedagem.
  • Referência de tempo de compilação necessária para a ativação

Repositório de runtime

A implementação de inicialização de hospedagem é colocada no repositório de runtime. Uma referência de tempo de compilação para o assembly não é exigida pelo aplicativo aprimorado.

Depois que a inicialização de hospedagem é compilada, um repositório de runtime é gerado, usando o arquivo de projeto do manifesto e o comando do dotnet store.

dotnet store --manifest {MANIFEST FILE} --runtime {RUNTIME IDENTIFIER} --output {OUTPUT LOCATION} --skip-optimization

No aplicativo de exemplo (projeto RuntimeStore) é usado o seguinte comando:

dotnet store --manifest store.manifest.csproj --runtime win7-x64 --output ./deployment/store --skip-optimization

Para o runtime descobrir o repositório de runtime, o local do repositório de runtime é adicionado à variável de ambiente DOTNET_SHARED_STORE.

Modificar e colocar o arquivo de dependências da inicialização de hospedagem

Para ativar o aprimoramento sem uma referência de pacote ao aprimoramento, especifique as dependências adicionais do runtime com additionalDeps. additionalDeps permite que você:

  • Estenda o grafo de biblioteca do aplicativo fornecendo um conjunto de arquivos .deps.json adicionais a serem mesclados com o próprio arquivo .deps.json do aplicativo na inicialização.
  • Torne o assembly de inicialização de hospedagem detectável e carregável.

A abordagem recomendada para gerar o arquivo de dependências adicionais é:

  1. Executar o dotnet publish no arquivo de manifesto do repositório de runtime mencionado na seção anterior.
  2. Remover a referência do manifesto das bibliotecas e a seção runtime do arquivo .deps.json resultante.

No projeto de exemplo, a propriedade store.manifest/1.0.0 é removida das seções targets e libraries:

{
  "runtimeTarget": {
    "name": ".NETCoreApp,Version=v2.1",
    "signature": "4ea77c7b75ad1895ae1ea65e6ba2399010514f99"
  },
  "compilationOptions": {},
  "targets": {
    ".NETCoreApp,Version=v2.1": {
      "store.manifest/1.0.0": {
        "dependencies": {
          "StartupDiagnostics": "1.0.0"
        },
        "runtime": {
          "store.manifest.dll": {}
        }
      },
      "StartupDiagnostics/1.0.0": {
        "runtime": {
          "lib/netcoreapp2.1/StartupDiagnostics.dll": {
            "assemblyVersion": "1.0.0.0",
            "fileVersion": "1.0.0.0"
          }
        }
      }
    }
  },
  "libraries": {
    "store.manifest/1.0.0": {
      "type": "project",
      "serviceable": false,
      "sha512": ""
    },
    "StartupDiagnostics/1.0.0": {
      "type": "package",
      "serviceable": true,
      "sha512": "sha512-oiQr60vBQW7+nBTmgKLSldj06WNLRTdhOZpAdEbCuapoZ+M2DJH2uQbRLvFT8EGAAv4TAKzNtcztpx5YOgBXQQ==",
      "path": "startupdiagnostics/1.0.0",
      "hashPath": "startupdiagnostics.1.0.0.nupkg.sha512"
    }
  }
}

Coloque o arquivo .deps.json no seguinte local:

{ADDITIONAL DEPENDENCIES PATH}/shared/{SHARED FRAMEWORK NAME}/{SHARED FRAMEWORK VERSION}/{ENHANCEMENT ASSEMBLY NAME}.deps.json
  • {ADDITIONAL DEPENDENCIES PATH}: local adicionado à variável de ambiente DOTNET_ADDITIONAL_DEPS.
  • {SHARED FRAMEWORK NAME}: estrutura compartilhada necessária para esse arquivo de dependências adicionais.
  • {SHARED FRAMEWORK VERSION}: versão mínima de estrutura compartilhada.
  • {ENHANCEMENT ASSEMBLY NAME}: nome do assembly do aprimoramento.

No aplicativo de exemplo (projeto RuntimeStore), o arquivo de dependências adicionais é colocado no seguinte local:

deployment/additionalDeps/shared/Microsoft.AspNetCore.App/2.1.0/StartupDiagnostics.deps.json

Para o runtime descobrir o local do repositório de runtime, o local do arquivo de dependências adicionais é adicionado à variável de ambiente DOTNET_ADDITIONAL_DEPS.

No aplicativo de exemplo (projeto RuntimeStore), crie o repositório de tempo de execução e gere o arquivo de dependências adicionais usando um script PowerShell.

Para obter exemplos de como definir variáveis de ambiente para vários sistemas operacionais, confira Usar vários ambientes.

Implantação

Para facilitar a implantação de uma inicialização de hospedagem em um ambiente multicomputador, o aplicativo de exemplo cria uma pasta implantação na saída publicada que contém:

  • O repositório de runtime de inicialização de hospedagem.
  • O arquivo de dependências de inicialização de hospedagem.
  • Um script do PowerShell que cria ou modifica ASPNETCORE_HOSTINGSTARTUPASSEMBLIES, DOTNET_SHARED_STORE e DOTNET_ADDITIONAL_DEPS para dar suporte à ativação da inicialização de hospedagem. Execute o script de um prompt de comando do PowerShell administrativo no sistema de implantação.

Pacote NuGet

Uma melhoria da inicialização de hospedagem pode ser fornecida em pacote do NuGet. O pacote tem um atributo HostingStartup. Os tipos de inicialização de hospedagem fornecidos pelo pacote são disponibilizados para o aplicativo usando qualquer uma das seguintes abordagens:

  • O arquivo de projeto do aplicativo aprimorado faz uma referência de pacote para a inicialização de hospedagem no arquivo de projeto do aplicativo (uma referência de tempo de compilação). Com a referência de tempo de compilação em vigor, o assembly de inicialização de hospedagem e todas as suas dependências são incorporados ao arquivo de dependência do aplicativo (.deps.json). Essa abordagem se aplica a um pacote de assembly de inicialização de hospedagem publicado para nuget.org.
  • O arquivo de dependências da inicialização de hospedagem fica disponível para o aplicativo avançado, conforme descrito na seção Repositório de runtime (sem uma referência de tempo de compilação).

Para obter mais informações sobre pacotes do NuGet e o repositório de runtime, consulte os tópicos a seguir:

Pasta Lixeira do projeto

Uma melhoria da inicialização de hospedagem pode ser fornecida por um assemby implantado na lixeira no aplicativo aprimorado. Os tipos de inicialização de hospedagem fornecidos pelo assembly são disponibilizados para o aplicativo usando uma das seguintes abordagens:

  • O arquivo de projeto do aplicativo aprimorado faz uma referência de assembly para a inicialização de hospedagem (uma referência de tempo de compilação). Com a referência de tempo de compilação em vigor, o assembly de inicialização de hospedagem e todas as suas dependências são incorporados ao arquivo de dependência do aplicativo (.deps.json). Essa abordagem se aplica quando o cenário de implantação demanda fazer uma referência de tempo de compilação ao assembly da inicialização de hospedagem (arquivo .dll) e mover o assembly para:
    • o projeto de consumo.
    • um local acessível ao projeto de consumo.
  • O arquivo de dependências da inicialização de hospedagem fica disponível para o aplicativo avançado, conforme descrito na seção Repositório de runtime (sem uma referência de tempo de compilação).
  • Ao ter como destino o .NET Framework, o assembly é carregável no contexto de carga padrão, o que, no .NET Framework, significa que ele fica em um dos seguintes locais:
    • Caminho da base de aplicativo: a pasta bin onde o executável do aplicativo(.exe) está localizado.
    • Cache de assembly global (GAC, na sigla em inglês): o GAC armazena assemblies que vários aplicativos .NET Framework compartilham. Para obter mais informações, consulte Instalação de um assembly no cache de assembly global na documentação do .NET Framework.

Código de exemplo

O código de exemplo (como baixar) demonstra cenários de implementação de inicialização de hospedagem:

  • Dois assemblies de inicialização de hospedagem (bibliotecas de classes) definem um par chave-valor de configuração na memória cada:
    • Pacote do NuGet (HostingStartupPackage)
    • Biblioteca de classes (HostingStartupLibrary)
  • Uma inicialização de hospedagem é ativada de um assembly implantado pelo repositório de runtime (StartupDiagnostics). O assembly adiciona dois middlewares ao aplicativo na inicialização que fornecem informações de diagnóstico sobre:
    • Serviços registrados
    • Endereço (esquema, host, base do caminho, caminho, cadeia de caracteres de consulta)
    • Conexão (IP remoto, porta remota, IP local, porta local, certificado do cliente)
    • Cabeçalhos da solicitação
    • Variáveis de ambiente

Para executar o exemplo:

Ativação de um pacote do NuGet

  1. Compile o pacote HostingStartupPackage com o comando dotnet pack.

  2. Adicione o nome do assembly do pacote do HostingStartupPackage para a variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES.

  3. Compile e execute o aplicativo. Uma referência de pacote está presente no aplicativo aprimorado (uma referência de tempo de compilação). Um <PropertyGroup> no arquivo de projeto do aplicativo especifica a saída do projeto de pacote (../HostingStartupPackage/bin/Debug) como uma origem de pacote. Isso permite que o aplicativo use o pacote sem carregar o pacote no nuget.org. Para obter mais informações, consulte as anotações no arquivo de projeto do HostingStartupApp.

    <PropertyGroup>
      <RestoreSources>$(RestoreSources);https://api.nuget.org/v3/index.json;../HostingStartupPackage/bin/Debug</RestoreSources>
    </PropertyGroup>
    
  4. Observe que os valores de chave de configuração do serviço renderizados pela página de índice correspondem aos valores definidos pelo método ServiceKeyInjection.Configure do pacote.

Se você fizer alterações no projeto HostingStartupPackage e recompilá-lo, limpe os caches de pacote do NuGet locais para garantir que o HostingStartupApp receba o pacote atualizado e não um pacote obsoleto do cache local. Para limpar os caches locais do NuGet, execute o seguinte comando dotnet nuget locals:

dotnet nuget locals all --clear

Ativação de uma biblioteca de classes

  1. Compile a biblioteca de classes HostingStartupLibrary com o comando dotnet build.

  2. Adicione nome do assembly da biblioteca de classes do HostingStartupLibrary à variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES.

  3. A pasta lixeira implanta o assembly da biblioteca de classes para o aplicativo ao copiar o arquivo HostingStartupLibrary.dll da saída compilada da biblioteca de classes para a pasta lixeira/Depurar do aplicativo.

  4. Compile e execute o aplicativo. Um <ItemGroup> do arquivo de projeto do aplicativo referencia o assembly da biblioteca de classes (.\lixeira\Depurar\netcoreapp2.1\HostingStartupLibrary.dll) (uma referência de tempo de compilação). Para mais informações, consulte as notas no arquivo de projeto do HostingStartupApp.

    <ItemGroup>
      <Reference Include=".\\bin\\Debug\\netcoreapp2.1\\HostingStartupLibrary.dll">
        <HintPath>.\bin\Debug\netcoreapp2.1\HostingStartupLibrary.dll</HintPath>
        <SpecificVersion>False</SpecificVersion>
      </Reference>
    </ItemGroup>
    
  5. Observe que os valores de chave de configuração do serviço renderizados pela página de índice correspondem aos valores definidos pelo método ServiceKeyInjection.Configure da biblioteca de classes.

Ativação de um assembly implantado pelo repositório de runtime

  1. O projeto StartupDiagnostics usa o PowerShell para modificar seu arquivo StartupDiagnostics.deps.json. O PowerShell é instalado por padrão em um sistema operacional Windows começando no Windows 7 SP1 e no Windows Server 2008 R2 SP1. Para obter o PowerShell em outras plataformas, consulte Instalando várias versões do PowerShell.
  2. Execute o script build.ps1 na pasta RuntimeStore. O script:
    • Gera o pacote StartupDiagnostics na pasta obj\packages.
    • Gera o repositório de runtime para StartupDiagnostics na pasta de armazenamento. O comando dotnet store no script usa o win7-x64RID (identificador de runtime) para uma inicialização de host implantada no Windows. Ao fornecer a inicialização de hospedagem para um runtime diferente, substitua pelo RID correto na linha 37 do script. O repositório de runtime para StartupDiagnostics posteriormente seria movido para o repositório de runtime do usuário ou do sistema no computador em que o assembly será consumido. O local de instalação do repositório de runtime do usuário para o assembly StartupDiagnostics é .dotnet/store/x64/netcoreapp2.2/startupdiagnostics/1.0.0/lib/netcoreapp2.2/StartupDiagnostics.dll.
    • Gera o additionalDeps para StartupDiagnostics na pasta additionalDeps. As dependências adicionais posteriormente seriam movidas para as dependências adicionais do usuário ou do sistema. O local de instalação de dependências adicionais do usuário StartupDiagnostics é .dotnet/x64/additionalDeps/StartupDiagnostics/shared/Microsoft.NETCore.App/2.2.0/StartupDiagnostics.deps.json.
    • Coloca o arquivo deploy.ps1 na pasta deployment.
  3. Execute o script deploy.ps1 na pasta deployment. O script acrescenta:
    • StartupDiagnostics à variável de ambiente ASPNETCORE_HOSTINGSTARTUPASSEMBLIES.
    • O caminho de dependências de inicialização de hospedagem (na pasta de implantação do projeto RuntimeStore) para a variável de ambiente DOTNET_ADDITIONAL_DEPS.
    • O caminho do repositório de runtime (na pasta de implantação do projeto RuntimeStore) para a variável de ambiente DOTNET_SHARED_STORE.
  4. Execute o aplicativo de exemplo.
  5. Solicite o ponto de extremidade /services para ver os serviços registrados do aplicativo. Solicite o ponto de extremidade /diag para ver as informações de diagnóstico.