Publicar no IIS, definindo Variável de ambiente


134

Lendo essas duas perguntas / respostas, consegui executar um aplicativo Asp.net 5 no servidor IIS 8.5.

Asp.net vNext beta inicial publicar no IIS no servidor Windows

Como configurar um aplicativo MVC6 para funcionar no IIS?

O problema é que o aplicativo Web ainda está usando env.EnvironmentNamevalor, Developmentmesmo quando executado no IIS.

Além disso, quero executar duas versões da mesma Web (armazenamento temporário, produção) no mesmo servidor, portanto, preciso de um método para definir a variável para cada Web separadamente.

Como fazer isso?


4
Um deles possui tipicamente três ambientes de rede, desenvolvimento, preparação e produção. O servidor da web está em um ambiente. Portanto, a configuração da variável de ambiente do sistema para o servidor normalmente não é uma restrição real. Ainda é possível usar Properties\launchSettings.jsonpara simular outro ambiente para depuração no Visual Studio.
21415 Oleg

Respostas:


286

Esta resposta foi originalmente escrita para o ASP.NET Core RC1. No RC2, o ASP.NET Core passou do manipulador httpPlafrom genérico para o aspnetCore específico. Observe que a etapa 3 depende de qual versão do ASP.NET Core você está usando.

Acontece que variáveis ​​de ambiente para projetos do ASP.NET Core podem ser definidas sem a necessidade de definir variáveis ​​de ambiente para o usuário ou a criação de várias entradas de comandos.

  1. Vá para o seu aplicativo no IIS e escolha Configuration Editor.
  2. Selecione Configuration Editor
  3. Escolha system.webServer/aspNetCore(RC2 e RTM) ou system.webServer/httpPlatform(RC1) na Sectioncaixa de combinação
  4. Escolha Applicationhost.config ...na Fromcaixa de combinação.
  5. Clique com o botão direito do mouse no enviromentVariableselemento, selecione e 'environmentVariables' element, em seguida Edit Items. insira a descrição da imagem aqui
  6. Defina suas variáveis ​​de ambiente.
  7. Feche a janela e clique em Aplicar.
  8. Feito

Dessa forma, você não precisa criar usuários especiais para o seu pool ou criar entradas de comandos extras no project.json. Além disso, a adição de comandos especiais para cada ambiente interrompe "criar uma vez, implantar várias vezes", pois você precisará chamar dnu publishseparadamente para cada ambiente, em vez de publicar uma vez e implantar o artefato resultante várias vezes.

Atualizado para RC2 e RTM, graças a Mark G e tredder.


12
Para o passo 3, usei em seu system.webServer/aspNetCorelugar.
Mark G

1
As variáveis ​​de ambiente do sistema são herdadas pelos processos no início. Portanto, se você alterar alguma variável env durante a execução do seu aplicativo, não poderá ver essas alterações por padrão. Para que as alterações de var de ambiente do sistema entrem em vigor, você precisará pelo menos reiniciar o site, talvez o pool ou até o serviço IIS, dependendo de como o IIS cria processos. Isso precisa ser testado.
NickAb

7
As configurações adicionadas pelo Editor de configuração não serão apagadas na próxima implantação?
Brad Gardner

11
@ brad-gardner se forem feitas alterações no Applicationhost.config em vez de web.config, as alterações serão persistidas entre as implantações.
NickAb

15
Funciona para o Asp.Net Core 2.0 #
Frank Cannon

34

Atualize web.config com uma seção <environmentVariables> em <aspNetCore>

<configuration>
  <system.webServer>
    <aspNetCore .....>
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>
    </aspNetCore>
  </system.webServer>
</configuration>

Ou, para evitar perder essa configuração ao substituir o web.config, faça alterações semelhantes ao applicationHost.config especificando o local do site, como sugere o @NickAb.

<location path="staging.site.com">
    <system.webServer>
        <aspNetCore>
            <environmentVariables>
                <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
            </environmentVariables>
        </aspNetCore>
    </system.webServer>
</location>
<location path="production.site.com">
    <system.webServer>
        <aspNetCore>
            <environmentVariables>
                <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" />
            </environmentVariables>
        </aspNetCore>
    </system.webServer>
</location>

2
Isso é diferente de uma maneira que o seu web.config faz parte do projeto e é versionado no VCS. Se você tiver vários ambientes, como prod, staging, dev, precisará de uma maneira de transformar o web.config para cada um. Alterar ApplicationHost.config no IIS afeta apenas este IIS. Para que você possa ter web.config único em seu VCS e variáveis ​​de ambiente específicas do IIS que substituam as variáveis ​​web.config. ApplicationHost.config podem ser editados através de programação usando PowerShell iis.net/learn/manage/powershell/...
NickAb

Obrigado @NickAb, que evita a necessidade de atualizar o web.config a cada implantação. Eu atualizei minha resposta.
Trevor Daniels

Estou tendo problemas para fazer isso no PowerShell. Eu continuo recebendo Target configuration object '/system.webServer/aspNetCore/environmentVariables/environmentVariable is not found ... normalmente para definir alguma variável. Eu escreveria algo assim: o Set-WebConfigurationProperty -PSPath IIS:\ -location example.com -filter /system.webServer/aspNetCore/environmentVariables/environmentVariable -name ASPNETCORE_ENVIRONMENT -value Staging que estou perdendo?
Christian

Voltei ao que conhecia e usei appcmd.
Christian

@Christian, veja esta resposta: stackoverflow.com/a/50869935/33533 A variável de ambiente nome e o valor de ir em uma tabela hash, então a partir de seu exemplo seriaSet-WebConfigurationProperty -PSPath IIS:\ -Location example.com -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = 'Staging' }
Curtis Buys

21

Edit: a partir das versões RC2 e RTM, este conselho está desatualizado. A melhor maneira que encontrei para fazer isso na versão é editar as seguintes seções web.config no IIS para cada ambiente:

system.webServer/aspNetCore:

Edite a entrada environmentVariable e adicione uma configuração de variável de ambiente:

ASPNETCORE_ENVIRONMENT : < Your environment name >


Como alternativa à abordagem do drpdrp, você pode fazer o seguinte:

  • No seu project.json, adicione comandos que transmitem a variável ASPNET_ENV diretamente ao Kestrel:

    "commands": {
        "Development": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Development",
        "Staging": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Staging",
        "Production": "Microsoft.AspNet.Server.Kestrel --ASPNET_ENV Production"
    }
    
  • Ao publicar, use a --iis-commandopção para especificar um ambiente:

    dnu publish --configuration Debug --iis-command Staging --out "outputdir" --runtime dnx-clr-win-x86-1.0.0-rc1-update1
    

Achei essa abordagem menos invasiva do que a criação de usuários extras do IIS.


11
Se você estiver publicando através do msdeploy do visual studio. Em seguida, você pode colocar o <IISCommand> Staging </IISCommand> em seu arquivo .pubxml e ele será implantado usando o comando IIS especificado, mesmo que você não possa especificá-lo na interface de publicação.
Dean Norte

@DeanNorth - Isso é dourado !! Funciona como um campeão! Obrigado por compartilhar!
S. Rasmussen

17

Eu tenho meus aplicativos Web (PRODUÇÃO, STAGING, TEST) hospedados no servidor Web IIS. Portanto, não foi possível confiar na variável de ambiente do sistema do operador ASPNETCORE_ENVIRONMENT, porque configurá-la para um valor específico (por exemplo, STAGING) afeta outros aplicativos.

Como solução alternativa, defini um arquivo personalizado (envsettings.json) na minha solução do visualstudio:

insira a descrição da imagem aqui

com o seguinte conteúdo:

{
  // Possible string values reported below. When empty it use ENV variable value or Visual Studio setting.
  // - Production
  // - Staging
  // - Test
  // - Development
  "ASPNETCORE_ENVIRONMENT": ""
}

Em seguida, com base no meu tipo de aplicativo (produção, teste ou teste), defino este arquivo de acordo: supondo que estou implantando o aplicativo TEST, terei:

"ASPNETCORE_ENVIRONMENT": "Test"

Depois disso, no arquivo Program.cs, recupere esse valor e defina o ambiente do webHostBuilder:

    public class Program
    {
        public static void Main(string[] args)
        {
            var currentDirectoryPath = Directory.GetCurrentDirectory();
            var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json");
            var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath));
            var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();

            var webHostBuilder = new WebHostBuilder()
                .UseKestrel()
                .CaptureStartupErrors(true)
                .UseSetting("detailedErrors", "true")
                .UseContentRoot(currentDirectoryPath)
                .UseIISIntegration()
                .UseStartup<Startup>();

            // If none is set it use Operative System hosting enviroment
            if (!string.IsNullOrWhiteSpace(enviromentValue)) 
            { 
                webHostBuilder.UseEnvironment(enviromentValue);
            }

            var host = webHostBuilder.Build();

            host.Run();
        }
    }

Lembre-se de incluir o envsettings.json no publishOptions (project.json):

  "publishOptions":
  {
    "include":
    [
      "wwwroot",
      "Views",
      "Areas/**/Views",
      "envsettings.json",
      "appsettings.json",
      "appsettings*.json",
      "web.config"
    ]
  },

Essa solução me deixa livre para ter o aplicativo ASP.NET CORE hospedado no mesmo IIS, independentemente do valor da variável do ambiente.


Muito bom, a única alteração que sugiro é swap var currentDirectoryPath = Directory.GetCurrentDirectory (); for var currentDirectoryPath = PlatformServices.Default.Application.ApplicationBasePath; Essa é uma maneira muito mais segura de obter o diretório atual.
Peter Kottas

7
Que grande proveito da experiência de caixa, quando você tem que criar uma outra camada de configurações para gerenciar configurações de um quadro
Kugel

16

Depois de pesquisar bastante, encontrei uma solução funcional, que consiste em duas etapas.

A primeira etapa é definir a variável de ambiente ASPNET_ENV para todo o sistema como Produção e reiniciar o Windows Server . Depois disso, todos os aplicativos da Web estão recebendo o valor 'Production' como EnvironmentName.

A segunda etapa (para habilitar o valor 'Preparação' para a Web de preparação) foi bastante mais difícil de funcionar corretamente, mas aqui está:

  1. Crie um novo usuário do Windows, por exemplo, StagingPool no servidor.
  2. Para esse usuário, crie uma nova variável de usuário ASPNETCORE_ENVIRONMENT com o valor 'Staging' (você pode fazer isso efetuando login como esse usuário ou através do regedit)
  3. De volta como administrador no gerenciador do IIS, localize o Pool de aplicativos no qual a Web de armazenamento temporário está sendo executada e, em Configurações avançadas, defina Identity como usuário StagingPool .
  4. Defina também Load User Profile como true , para que as variáveis ​​de ambiente sejam carregadas. <- muito importante!
  5. Verifique se o StagingPool tem direitos de acesso à pasta da web e Interrompa e inicie o pool de aplicativos.

Agora, a Web de armazenamento temporário deve ter o Nome do ambiente definido como 'Armazenamento temporário'.

Atualização: no Windows 7 ou superior, existe um comando que pode definir variáveis ​​de ambiente no prompt do CMD também para um usuário especificado. Isso gera mais exemplos de ajuda:

>setx /?

1
Parece que no ASP.NET 5 RC1, a variável de ambiente foi alterada para Hosting: Environment.
Grady Werner

Como definir "Carregar perfil de usuário" como verdadeiro quando implantamos isso no Azure Web App?
Puneet Ghanshani

@PunitGanshani Pelo que entendi, há uma seção "configurações do aplicativo" no portal do azure para aplicativo da web em que você pode definir pares de chave / valor do ambiente: azure.microsoft.com/en-us/documentation/articles/…
drpdrp

@GradyWerner Para RC2 eles estão mudando isso (a partir de agora) para ASPNET_ENVIRONMENT ;-)
b.pell

1
@ b.pell Parece agora é ASPNETCORE_ENVIRONMENT :)
Mark G

11

Como alternativa, você pode passar o desejado ASPNETCORE_ENVIRONMENTpara o comando dotnet publish como um argumento usando:

/p:EnvironmentName=Staging

por exemplo:

dotnet publish /p:Configuration=Release /p:EnvironmentName=Staging

Isso gerará o web.config com o ambiente correto especificado para o seu projeto:

<environmentVariables>
  <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>

9

Além das opções mencionadas acima, existem algumas outras soluções que funcionam bem com implantações automatizadas ou exigem menos alterações na configuração.

1. Modificando o arquivo de projeto (.CsProj)

O MSBuild suporta a EnvironmentNamepropriedade, que pode ajudar a definir a variável de ambiente correta conforme o ambiente que você deseja implantar. O nome do ambiente seria adicionado no web.config durante a fase de publicação.

Simplesmente abra o arquivo do projeto (* .csProj) e adicione o seguinte XML.

<!-- Custom Property Group added to add the Environment name during publish
  The EnvironmentName property is used during the publish for the Environment variable in web.config
  -->
  <PropertyGroup Condition=" '$(Configuration)' == '' Or '$(Configuration)' == 'Debug'">
    <EnvironmentName>Development</EnvironmentName>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)' != '' AND '$(Configuration)' != 'Debug' ">
    <EnvironmentName>Production</EnvironmentName>
  </PropertyGroup>

O código acima adicionaria o nome do ambiente da Developmentconfiguração de depuração ou se nenhuma configuração for especificada. Para qualquer outra configuração, o nome do ambiente estaria Productionno arquivo web.config gerado. Mais detalhes aqui

2. Adicionando a propriedade EnvironmentName nos perfis de publicação.

Também podemos adicionar a <EnvironmentName>propriedade no perfil de publicação. Abra o arquivo de perfil de publicação localizado em Properties/PublishProfiles/{profilename.pubxml}Isso definirá o nome do ambiente em web.config quando o projeto for publicado. Mais detalhes aqui

<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

3. Opções de linha de comando usando a publicação dotnet

Além disso, podemos passar a propriedade EnvironmentNamecomo uma opção de linha de comando para o dotnet publishcomando. O comando a seguir incluiria a variável de ambiente como Developmentno arquivo web.config.

dotnet publish -c Debug -r win-x64 /p:EnvironmentName=Development


7

Para estender a resposta do @ tredder, você pode alterar o environmentVariables usando appcmd

Estadiamento

%windir%\system32\inetsrv\appcmd set config "staging.example.com" /section:system.webServer/aspNetCore /+environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Staging'] /commit:APPHOST

Produção

%windir%\system32\inetsrv\appcmd set config "example.com" /section:system.webServer/aspNetCore /+environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='Production'] /commit:APPHOST


Aqui está como fazer a mesma coisa com o Powershell em um servidor de compilação sem o IIS instalado. gist.github.com/markarnott/c4aec1fc544fe89e2bd21f3f00d78933
Mark Arnott

A especificação de "staging.example.com" ou "example.com" aplicará apenas a variável a esses sites específicos. Omitir que criará uma variável global para todos os sites no servidor.
Deadlydog 18/05/19

6

O que você precisa saber em um só lugar:

  • Para que as variáveis ​​de ambiente substituam quaisquer definições de configuração, elas devem ser prefixadas ASPNETCORE_.
  • Se você deseja corresponder nós filhos na sua configuração JSON, use :como separador. Se a plataforma não permitir dois pontos nas chaves de variável de ambiente, use-a __.
  • Você deseja que suas configurações terminem ApplicationHost.config. O uso do Editor de configuração do IIS fará com que suas entradas sejam gravadas no aplicativo Web.config- e serão substituídas na próxima implantação!
  • Para modificar ApplicationHost.config, você deseja usar appcmd.exepara garantir que suas modificações sejam consistentes. Exemplo:%systemroot%\system32\inetsrv\appcmd.exe set config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore /+"environmentVariables.[name='ASPNETCORE_AWS:Region',value='eu-central-1']" /commit:site

  • Os caracteres que não são seguros para URL podem ser escapados como Unicode, como %u007bno colchete esquerdo.

  • Para listar suas configurações atuais (combinadas com valores de Web.config): %systemroot%\system32\inetsrv\appcmd.exe list config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore
  • Se você executar o comando para definir uma chave de configuração várias vezes para a mesma chave, ela será adicionada várias vezes! Para remover um valor existente, use algo como %systemroot%\system32\inetsrv\appcmd.exe set config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore /-"environmentVariables.[name='ASPNETCORE_MyKey',value='value-to-be-removed']" /commit:site.

1
Observe que, com /commit:siteas alterações são gravadas no web.config, a fim de salvá-los no ApplicationHost.configdeve-se usar/commit:apphost
Anjo Yordanov

-section:system.webServer/aspNetCore /-"environmentVariables.(com menos para remover a variável de ambiente) falha ao ser executada durante o pipeline de lançamento do Azure. O erro é hresult:80070032, message:Command execution failed. No entanto, clear config "Default Web Site/$(webSiteName)" -section:system.webServer/aspNetCore /commit:sitefunciona bem. Ele limpa toda a seção aspNetCore do site, mas não é um problema, pois é parametrizado durante o lançamento.
Olaksa

6

Semelhante a outras respostas, eu queria garantir que minha configuração de ambiente do ASP.NET Core 2.1 persistisse nas implantações, mas também se aplicasse apenas ao site específico.

De acordo com a documentação da Microsoft, é possível definir a variável de ambiente no pool de aplicativos usando o seguinte comando do PowerShell no IIS 10:

$appPoolName = "AppPool"
$envName = "Development"
cd "$env:SystemRoot\system32\inetsrv"
.\appcmd.exe set config -section:system.applicationHost/applicationPools /+"[name='$appPoolName'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='$envName']" /commit:apphost

Infelizmente ainda tenho que usar o IIS 8.5 e pensei que estava sem sorte. No entanto, ainda é possível executar um script simples do PowerShell para definir um valor de variável de ambiente específico do site para ASPNETCORE_ENVIRONMENT:

Import-Module -Name WebAdministration
$siteName = "Site"
$envName = "Development"
Set-WebConfigurationProperty -PSPath IIS:\ -Location $siteName -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = $envName }

5

A solução @tredder com edição applicationHost.config é a que funciona se você tiver vários aplicativos diferentes localizados em diretórios virtuais no IIS.

Meu caso é:

  • Eu tenho projeto API e projeto APP , no mesmo domínio, colocados em diretórios virtuais diferentes
  • A página raiz XXX parece não propagar a variável ASPNETCORE_ENVIRONMENT para seus filhos em diretórios virtuais e ...
  • ... Não consigo definir as variáveis ​​dentro do diretório virtual como @NickAb descrito (erro obtido A solicitação não é suportada. (Exceção de HRESULT: 0x80070032) durante a gravação de alterações no Editor de configuração):
  • Indo para applicationHost.config e criando nós manualmente como este:

    <location path="XXX/app"> <system.webServer> <aspNetCore> <environmentVariables> <clear /> <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" /> </environmentVariables> </aspNetCore> </system.webServer> </location> <location path="XXX/api"> <system.webServer> <aspNetCore> <environmentVariables> <clear /> <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" /> </environmentVariables> </aspNetCore> </system.webServer> </location>

e reiniciar o IIS fez o trabalho.


0

Para obter os detalhes sobre o erro, tive que adicionar ASPNETCORE_ENVIRONMENTuma variável de ambiente ao pool de aplicativos correspondente system.applicationHost/applicationPools .

Nota: o aplicativo Web, no meu caso, era ASP.NET Core 2um aplicativo Web hospedado em IIS 10. Isso pode ser feito via Configuration Editorin IIS Manager(consulte Editando coleções com o Editor de configuração para descobrir onde encontrar esse editor IIS Manager).


0

Eu criei um repositório para publicar o IIS com a configuração do ambiente no Web.config.

https://github.com/expressiveco/AspnetCoreWebConfigForEnvironment

  • Configuração
    • Obtenha as seções dos arquivos .csproj e .user.csproj nos arquivos do projeto.
    • Obtenha os arquivos MyAspNetEnvironment.props, web.development.config e web.production.config.
  • Configuração
    • Altere o valor da propriedade ASPNETCORE_ENVIRONMENT em user.csproj relevante.

Isso não parece fornecer uma resposta de qualidade à pergunta. Edite sua resposta adicionando os detalhes gerais desta solução ou remova-a e publique-a como um comentário na pergunta. Obrigado!
sɐunıɔ ןɐ qɐp

0

Modifiquei a resposta que é dada por @Christian Del Bianco . Alterei o processo para .net core 2 e superior como arquivo project.json agora absoluto.

  1. Primeiro, crie o arquivo appsettings.json no diretório raiz. com o conteúdo

      {
         // Possible string values reported below. When empty it use ENV 
            variable value or Visual Studio setting.
         // - Production
         // - Staging
         // - Test
        // - Development
       "ASPNETCORE_ENVIRONMENT": "Development"
     }
    
  2. Em seguida, crie outro arquivo de configuração appsettings.Development.json e appsettings.Production.json com a configuração necessária.

  3. Adicione o código necessário para configurar o ambiente no arquivo Program.cs .

    public class Program
    {
    public static void Main(string[] args)
    {
        var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    
      ***var currentDirectoryPath = Directory.GetCurrentDirectory();
        var envSettingsPath = Path.Combine(currentDirectoryPath, "envsettings.json");
        var envSettings = JObject.Parse(File.ReadAllText(envSettingsPath));
        var enviromentValue = envSettings["ASPNETCORE_ENVIRONMENT"].ToString();***
    
        try
        {
            ***CreateWebHostBuilder(args, enviromentValue).Build().Run();***
        }
        catch (Exception ex)
        {
            //NLog: catch setup errors
            logger.Error(ex, "Stopped program because of setup related exception");
            throw;
        }
        finally
        {
            NLog.LogManager.Shutdown();
        }
    }
    
    public static IWebHostBuilder CreateWebHostBuilder(string[] args, string enviromentValue) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup<Startup>()
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
            })
            .UseNLog()
            ***.UseEnvironment(enviromentValue);***
    

    }

  4. Adicione o envsettings.json ao seu .csproj arquivo para copiar para o diretório publicado.

       <ItemGroup>
            <None Include="envsettings.json" CopyToPublishDirectory="Always" />
        </ItemGroup>
    
  5. Agora basta alterar o ASPNETCORE_ENVIRONMENT conforme desejado no arquivo envsettings.json e publicado.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.