Publicar en IIS, configurando la variable de entorno

134

Al leer estas dos preguntas / respuestas pude ejecutar una aplicación Asp.net 5 en el servidor IIS 8.5.

Asp.net vNext beta temprana publica en IIS en Windows Server

¿Cómo configurar una aplicación MVC6 para que funcione en IIS?

El problema es que la aplicación web todavía está usando env.EnvironmentNamevalor Developmentincluso cuando se ejecuta en IIS.

Además, quiero ejecutar dos versiones de la misma Web (Puesta en escena, Producción) en el mismo servidor, por lo que necesito un método para establecer la variable para cada Web por separado.

¿Como hacer esto?

drpdrp
fuente
44
Uno tiene típicamente tres entornos de red Desarrollo, Puesta en escena y Producción. El servidor web está en uno el entorno. Por lo tanto, la configuración de la variable de entorno del sistema para el servidor no suele ser una restricción real. Todavía se puede usar Properties\launchSettings.jsonpara simular otro entorno para la depuración en Visual Studio.
Oleg

Respuestas:

286

Esta respuesta se escribió originalmente para ASP.NET Core RC1. En RC2, ASP.NET Core pasó de un controlador genérico httpPlafrom a uno específico de aspnetCore. Tenga en cuenta que el paso 3 depende de la versión de ASP.NET Core que esté utilizando.

Resulta que las variables de entorno para los proyectos ASP.NET Core se pueden establecer sin tener que establecer variables de entorno para el usuario o tener que crear múltiples entradas de comandos.

  1. Vaya a su aplicación en IIS y elija Configuration Editor.
  2. Seleccione Configuration Editor
  3. Elija system.webServer/aspNetCore(RC2 y RTM) o system.webServer/httpPlatform(RC1) en el Sectioncuadro combinado
  4. Elija Applicationhost.config ...en el Fromcuadro combinado.
  5. Haga clic derecho en el enviromentVariableselemento, seleccione 'environmentVariables' element, luego Edit Items. ingrese la descripción de la imagen aquí
  6. Establece tus variables de entorno.
  7. Cierre la ventana y haga clic en Aplicar.
  8. Hecho

De esta manera, no tiene que crear usuarios especiales para su grupo ni crear entradas de comandos adicionales project.json. Además, al agregar comandos especiales para cada entorno se rompe "compilar una vez, desplegar muchas veces", ya que tendrá que llamar dnu publishpor separado para cada entorno, en lugar de publicar una vez y desplegar el artefacto resultante muchas veces.

Actualizado para RC2 y RTM, gracias a Mark G y tredder.

NickAb
fuente
12
Para el paso 3 usé en su system.webServer/aspNetCorelugar.
Mark G
1
Las variables de entorno del sistema son heredadas por los procesos al inicio. Entonces, si cambia alguna variable env durante la ejecución de su aplicación, no podrá ver estos cambios de forma predeterminada. Para que los cambios en el entorno del sistema surtan efecto, necesitará al menos reiniciar el sitio, tal vez el grupo o incluso el servicio IIS, dependiendo de cómo IIS cree los procesos. Esto necesita ser probado.
NickAb
77
¿No se eliminarán las configuraciones agregadas a través del Editor de configuración en la próxima implementación?
Brad Gardner
11
@ brad-gardner si se realizan cambios en Applicationhost.config en lugar de web.config, los cambios se mantendrán entre implementaciones.
NickAb
15
Funciona para Asp.Net Core 2.0
Frank Cannon
34

Actualice web.config con una sección <environmentVariables> en <aspNetCore>

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

O para evitar perder esta configuración al sobrescribir web.config, realice cambios similares en applicationHost.config especificando la ubicación del sitio como sugiere @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>
Trevor Daniels
fuente
2
Esto es diferente en una forma en que su web.config es parte del proyecto y está versionado en VCS. Si tiene múltiples entornos, como prod, staging, dev, necesitará alguna forma de transformar web.config para cada uno. Cambiar ApplicationHost.config en IIS afecta solo a este IIS. Para que pueda tener solo web.config en su VCS y variables de entorno específicas de IIS que anulen las variables de web.config. ApplicationHost.config se puede editar mediante programación usando PowerShell iis.net/learn/manage/powershell/…
NickAb
Gracias @NickAb, eso evita tener que actualizar web.config en cada implementación. He actualizado mi respuesta.
Trevor Daniels
Tengo problemas para hacer esto desde PowerShell que sigo obteniendo Target configuration object '/system.webServer/aspNetCore/environmentVariables/environmentVariable is not found ... Normalmente para establecer alguna variable, escribiría algo como esto: Set-WebConfigurationProperty -PSPath IIS:\ -location example.com -filter /system.webServer/aspNetCore/environmentVariables/environmentVariable -name ASPNETCORE_ENVIRONMENT -value Staging ¿qué me estoy perdiendo?
Christian
Volví a lo que sabía y usé en su appcmdlugar.
Christian
@Christian, mira esta respuesta: stackoverflow.com/a/50869935/33533 El nombre y el valor de la variable de entorno van en una tabla hash, por lo que, según tu ejemplo, seríaSet-WebConfigurationProperty -PSPath IIS:\ -Location example.com -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = 'Staging' }
Curtis compra el
21

Editar: a partir de los lanzamientos de RC2 y RTM, este consejo está desactualizado. La mejor manera que he encontrado para lograr esto en la versión es editar las siguientes secciones web.config en IIS para cada entorno:

system.webServer/aspNetCore:

Edite la entrada variable de entorno y agregue una configuración de variable de entorno:

ASPNETCORE_ENVIRONMENT : < Your environment name >


Como alternativa al enfoque de drpdrp, puede hacer lo siguiente:

  • En su project.json, agregue comandos que pasen la variable ASPNET_ENV directamente a 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"
    }
    
  • Al publicar, use la --iis-commandopción para especificar un entorno:

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

Encontré que este enfoque es menos intrusivo que crear usuarios adicionales de IIS.

Joshua Barron
fuente
11
Si está publicando a través de msdeploy de Visual Studio. Luego puede poner <IISCommand> Staging </IISCommand> en su archivo .pubxml y se implementará utilizando el comando IIS especificado aunque no pueda especificarlo en la IU de publicación.
Dean North
@DeanNorth - ¡Esto es dorado! Funciona como un campeón! ¡Gracias por compartir!
S. Rasmussen
17

Tengo mis aplicaciones web (PRODUCCIÓN, ESCENARIO, PRUEBA) alojadas en el servidor web IIS. Por lo tanto, no fue posible confiar en la variable de entorno del sistema operativo ASPNETCORE_ENVIRONMENT, porque establecerla en un valor específico (por ejemplo, STAGING) tiene efecto en otras aplicaciones.

Como solución alternativa, definí un archivo personalizado (envsettings.json) dentro de mi solución visualstudio:

ingrese la descripción de la imagen aquí

con el siguiente contenido:

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

Luego, según mi tipo de aplicación (Producción, Puesta en escena o Prueba) configuré este archivo de forma acorde: suponiendo que estoy implementando la aplicación TEST, tendré:

"ASPNETCORE_ENVIRONMENT": "Test"

Después de eso, en el archivo Program.cs solo recupere este valor y luego configure el entorno de 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();
        }
    }

Recuerde incluir el envsettings.json en PublishOptions (project.json):

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

Esta solución me permite tener la aplicación ASP.NET CORE alojada en el mismo IIS, independientemente del valor de la variable de entorno.

Christian Del Bianco
fuente
Muy bien, el único cambio que sugiero es intercambiar var currentDirectoryPath = Directory.GetCurrentDirectory (); para var currentDirectoryPath = PlatformServices.Default.Application.ApplicationBasePath; Esta es una forma mucho más segura de obtener el directorio actual.
Peter Kottas
77
Qué gran experiencia fuera de la caja, cuando tienes que crear otra capa de configuraciones para administrar las configuraciones de un marco
Kugel
16

Después de buscar en Google, encontré una solución que consta de dos pasos.

El primer paso es establecer la variable de entorno de todo el sistema ASPNET_ENV en Producción y reiniciar el servidor de Windows . Después de esto, todas las aplicaciones web obtienen el valor 'Producción' como EnvironmentName.

El segundo paso (para habilitar el valor 'Puesta en escena' para la puesta en escena web) fue bastante más difícil de hacer funcionar correctamente, pero aquí está:

  1. Cree un nuevo usuario de Windows, por ejemplo, StagingPool en el servidor.
  2. Para este usuario, cree una nueva variable de usuario ASPNETCORE_ENVIRONMENT con el valor 'Staging' (puede hacerlo iniciando sesión como este usuario o mediante regedit)
  3. Volver como administrador en el administrador de IIS, encontrar el grupo de aplicaciones con la que la banda estadificación se está ejecutando y en Configuración avanzada para establecer la identidad del usuario StagingPool .
  4. También establezca Cargar perfil de usuario en verdadero , de modo que se carguen las variables de entorno. <- muy importante!
  5. Asegúrese de que StagingPool tenga derechos de acceso a la carpeta web y detenga e inicie el grupo de aplicaciones.

Ahora la web de ensayo debe tener el nombre de entorno establecido en "ensayo".

Actualización: en Windows 7+ hay un comando que puede establecer variables de entorno desde el indicador CMD también para un usuario específico. Esto genera ayuda más muestras:

>setx /?
drpdrp
fuente
1
Parece que en ASP.NET 5 RC1, la variable de entorno se cambió a Hosting: Environment.
Grady Werner
¿Cómo establecemos "Cargar perfil de usuario" en verdadero cuando implementamos esto en Azure Web App?
Puneet Ghanshani
@PunitGanshani Según tengo entendido, hay una sección de "configuración de la aplicación" en el portal azure para aplicaciones web donde puede establecer pares clave / valor de entorno: azure.microsoft.com/en-us/documentation/articles/…
drpdrp
@GradyWerner Para RC2 lo están cambiando (a partir de ahora) a ASPNET_ENVIRONMENT ;-)
b.pell
1
@ b.pell Parece que ahora es ASPNETCORE_ENVIRONMENT :)
Mark G
11

Alternativamente, podría pasar el deseado ASPNETCORE_ENVIRONMENTen el comando de publicación dotnet como argumento usando:

/p:EnvironmentName=Staging

p.ej:

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

Esto generará web.config con el entorno correcto especificado para su proyecto:

<environmentVariables>
  <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>
Sheldon Nunes
fuente
9

Además de las opciones mencionadas anteriormente, hay un par de otras Soluciones que funcionan bien con implementaciones automatizadas o requieren menos cambios de configuración.

1. Modificación del archivo del proyecto (.CsProj)

MSBuild admite la EnvironmentNamepropiedad que puede ayudar a establecer la variable de entorno correcta según el entorno que desea implementar. El nombre del entorno se agregaría en web.config durante la fase de publicación.

Simplemente abra el archivo del proyecto (* .csProj) y agregue el siguiente 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>

El código anterior agregaría el nombre del entorno como Developmentpara la configuración de depuración o si no se especifica ninguna configuración. Para cualquier otra configuración, el nombre del entorno estaría Productionen el archivo web.config generado. Más detalles aquí

2. Agregar la propiedad EnvironmentName en los perfiles de publicación.

También podemos agregar la <EnvironmentName>propiedad en el perfil de publicación. Abra el archivo de perfil de publicación que se encuentra en Properties/PublishProfiles/{profilename.pubxml}Esto configurará el nombre del Entorno en web.config cuando se publique el proyecto. Más detalles aquí

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

3. Opciones de línea de comando usando dotnet Publish

Además, podemos pasar la propiedad EnvironmentNamecomo una opción de línea de comando al dotnet publishcomando. El siguiente comando incluiría la variable de entorno como Developmenten el archivo web.config.

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

Abhinav Galodha
fuente
7

Para ampliar la respuesta de @ tredder, puede modificar el entorno Variables utilizando appcmd

Puesta en escena

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

Producción

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

cristiano
fuente
Aquí se explica cómo lograr lo mismo con Powershell en un servidor de compilación sin IIS instalado. gist.github.com/markarnott/c4aec1fc544fe89e2bd21f3f00d78933
Mark Arnott
Si especifica "staging.example.com" o "example.com" solo se aplicará la variable a esos sitios web específicos. Omitir eso creará una variable global para todos los sitios web en el servidor.
deadlydog
6

Lo que necesitas saber en un solo lugar:

  • Para que las variables de entorno anulen cualquier configuración, deben tener el prefijo ASPNETCORE_.
  • Si desea hacer coincidir los nodos secundarios en su configuración JSON, úselos :como separador. Si la plataforma no permite dos puntos en las teclas de variable de entorno, __úsela.
  • Desea que su configuración termine en ApplicationHost.config. El uso del Editor de configuración de IIS hará que sus entradas se escriban en la aplicación, ¡ Web.configy se sobrescribirán con la próxima implementación!
  • Para modificar ApplicationHost.config, desea usar appcmd.exepara asegurarse de que sus modificaciones sean consistentes. Ejemplo:%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

  • Los caracteres que no son seguros para URL se pueden escapar como Unicode, como %u007bpara el corchete izquierdo.

  • Para enumerar su configuración actual (combinada con valores de Web.config): %systemroot%\system32\inetsrv\appcmd.exe list config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore
  • Si ejecuta el comando para establecer una clave de configuración varias veces para la misma clave, ¡se agregará varias veces! Para eliminar un 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.
realMarkusSchmidt
fuente
1
tenga en cuenta que con /commit:sitelos cambios están escritos en la web.config, para guardarlos en el ApplicationHost.configque debe usar/commit:apphost
Angel Yordanov
-section:system.webServer/aspNetCore /-"environmentVariables.(con menos para eliminar la variable de entorno) no se puede ejecutar durante la canalización de lanzamiento de Azure. El error es hresult:80070032, message:Command execution failed. Sin embargo clear config "Default Web Site/$(webSiteName)" -section:system.webServer/aspNetCore /commit:sitefunciona bien. Borra toda la sección aspNetCore para el sitio web, pero no es un problema, ya que se parametriza durante el lanzamiento.
oleksa
6

Al igual que otras respuestas, quería asegurarme de que mi configuración de entorno ASP.NET Core 2.1 persistiera en todas las implementaciones, pero que solo se aplicara al sitio específico.

Según la documentación de Microsoft, es posible establecer la variable de entorno en el grupo de aplicaciones utilizando el siguiente comando de PowerShell en 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

Desafortunadamente, todavía tengo que usar IIS 8.5 y pensé que no tenía suerte. Sin embargo, todavía es posible ejecutar un script simple de PowerShell para establecer un valor de variable de entorno específico del sitio 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 }
dasch88
fuente
5

La solución @tredder con aplicación de edición Host.config es la que funciona si tiene varias aplicaciones diferentes ubicadas dentro de directorios virtuales en IIS.

Mi caso es:

  • Tengo un proyecto API y un proyecto APP , bajo el mismo dominio, ubicados en diferentes directorios virtuales
  • La página raíz XXX no parece propagar la variable ASPNETCORE_ENVIRONMENT a sus hijos en directorios virtuales y ...
  • ... No puedo configurar las variables dentro del directorio virtual como se describe en @NickAb (error recibido La solicitud no es compatible. (Excepción de HRESULT: 0x80070032) durante el guardado de cambios en el Editor de configuración):
  • Entrando en applicationHost.config y creando manualmente nodos 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>

y reiniciar el IIS hizo el trabajo.

Bartosz Lenar
fuente
0

Para obtener los detalles sobre el error, tuve que agregar ASPNETCORE_ENVIRONMENTuna variable de entorno para el grupo de aplicaciones correspondiente system.applicationHost/applicationPools .

Nota: la aplicación web en mi caso era ASP.NET Core 2una aplicación web alojada en IIS 10. Se puede hacer a través de Configuration Editorin IIS Manager(consulte Edición de colecciones con el Editor de configuración para averiguar dónde encontrar este editor IIS Manager).

Dmitry Pavlov
fuente
0

He creado un repositorio para publicar IIS con la configuración del entorno en Web.config.

https://github.com/expressiveco/AspnetCoreWebConfigForEnvironment

  • Preparar
    • Obtenga las secciones de los archivos .csproj y .user.csproj en sus archivos de proyecto.
    • Obtenga los archivos MyAspNetEnvironment.props, web.development.config y web.production.config.
  • Configuración
    • Cambie el valor de la propiedad ASPNETCORE_ENVIRONMENT en user.csproj de manera relevante.
subcodificador
fuente
Esto no parece proporcionar una respuesta de calidad a la pregunta. Edite su respuesta agregando los detalles generales de esta solución o simplemente elimínela y publíquela como un comentario a la pregunta. ¡Gracias!
sɐunıɔ ןɐ qɐp
0

He modificado la respuesta que se da @Christian Del Bianco . Cambié el proceso para .net core 2 y superior como archivo project.json ahora absoluto.

  1. Primero, cree el archivo appsettings.json en el directorio raíz. con el contenido

      {
         // Possible string values reported below. When empty it use ENV 
            variable value or Visual Studio setting.
         // - Production
         // - Staging
         // - Test
        // - Development
       "ASPNETCORE_ENVIRONMENT": "Development"
     }
    
  2. Luego cree otros dos archivos de configuración appsettings.Development.json y appsettings.Production.json con la configuración necesaria.

  3. Agregue el código necesario para configurar el entorno al archivo 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. Agregue envsettings.json a su archivo .csproj para copiarlo en el directorio publicado.

       <ItemGroup>
            <None Include="envsettings.json" CopyToPublishDirectory="Always" />
        </ItemGroup>
    
  5. Ahora solo cambie el ASPNETCORE_ENVIRONMENT como desee en el archivo envsettings.json y publíquelo .

Md. Nazrul Islam
fuente