发布到IIS,设置环境变量

215

阅读这两个问题/答案后,我能够在IIS 8.5服务器上运行Asp.net 5应用程序。

Asp.net vNext早期测试版发布到Windows服务器上的IIS

如何配置MVC6应用程序在IIS上运行?

问题是,即使在IIS上运行,Web应用程序仍然使用值为“Development”的env.EnvironmentName

而且,我想在同一台服务器上运行相同Web的两个版本(暂存版和生产版),因此我需要一种方法来为每个Web单独设置变量。

如何做到这一点?


4
通常情况下,人们会有三种网络环境:开发、测试和生产。Web服务器处于其中一个 环境中。因此对于服务器设置系统环境变量通常不是真正的限制。在Visual Studio中,仍可以使用Properties\launchSettings.json模拟另一个环境以进行调试。 - Oleg
17个回答

438

这篇答案最初是为ASP.NET Core RC1编写的,而在RC2中,ASP.NET Core从通用http平台处理程序转移到了特定于AspNetCore的处理程序。请注意,步骤3取决于您使用的ASP.NET Core版本。

结果证明,可以在不设置用户环境变量或创建多个命令条目的情况下设置ASP.NET Core项目的环境变量。

  1. 进入IIS中的应用程序,选择“配置编辑器”。
  2. 选择“配置编辑器”
  3. 在“部分”组合框中选择“system.webServer/aspNetCore”(RC2和RTM)或“system.webServer/httpPlatform”(RC1)
  4. 在“来自”组合框中选择“Applicationhost.config ...”。
  5. 右键单击“enviromentVariables”元素,选择“'environmentVariables' element”,然后选择“编辑项目”。 enter image description here
  6. 设置您的环境变量。
  7. 关闭窗口并单击“应用”。
  8. 完成

这样,您就不必为池创建特殊用户或在project.json中创建额外的命令条目了。此外,为每个环境添加特殊命令会破坏“一次构建,多次部署”,因为您将不得不单独调用dnu publish以针对每个环境发布,而不是一次发布并多次部署生成的工件。

更新至RC2和RTM,感谢Mark G和tredder。


15
第三步我使用了system.webServer/aspNetCore - Mark G
16
通过配置编辑器添加的设置会在下次部署时被清除吗? - Brad Gardner
18
如果对 Applicationhost.config 进行更改而不是 web.config,则更改将在部署之间持续存在。 - NickAb
2
请注意,在您提供的指示中更改的是 web.config 而不是 applicationhost.config。在特定的 IIS 服务器上对 web.config 的任何更改都将在下一次部署时丢失。而对 applicationhost.config 的更改会在特定的 IIS 服务器之间的部署中保留。 - NickAb
16
适用于 Asp.Net Core 2.0 的作品。 - Frank Cannon
显示剩余15条评论

70

<aspNetCore>下添加一个<environmentVariables>部分,更新包含web.config的配置文件。

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

避免在覆盖web.config时丢失此设置,可以按照@NickAb的建议对"applicationHost.config"进行类似更改,指定站点位置。
<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>

3
这种情况与你的web.config是项目的一部分,并且在版本控制系统中进行版本控制不同。如果您有多个环境,例如生产环境、预发布环境和开发环境,则需要一些方法来为每个环境转换web.config。更改IIS中的ApplicationHost.config仅会影响该IIS。因此,您可以在VCS中拥有单个web.config,并具有专用于IIS的环境变量,以覆盖web.config变量。可以使用PowerShell编程方式编辑ApplicationHost.config http://www.iis.net/learn/manage/powershell/powershell-snap-in-changing-simple-settings-in-configuration-sections - NickAb
谢谢@NickAb,这样就避免了每次部署都要更新web.config的麻烦。我已经更新了我的回答。 - Trevor Daniels
我在使用PowerShell时遇到了麻烦,一直出现以下错误信息: 目标配置对象 '/system.webServer/aspNetCore/environmentVariables/environmentVariable' 未找到...通常,要设置某些变量,我会编写类似以下的代码: Set-WebConfigurationProperty -PSPath IIS:\ -location example.com -filter /system.webServer/aspNetCore/environmentVariables/environmentVariable -name ASPNETCORE_ENVIRONMENT -value Staging我错过了什么吗? - Christian
我回到了我熟悉的,使用了 appcmd - Christian
@Christian,看一下这个答案:https://stackoverflow.com/a/50869935/33533 环境变量的名称和值放在哈希表中,所以根据你的示例,它应该是 Set-WebConfigurationProperty -PSPath IIS:\ -Location example.com -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value @{ Name = 'ASPNETCORE_ENVIRONMENT'; Value = 'Staging' } - Curtis Buys

36

适用于.NET 6吗? - Kiquenet
根据文档页面的版本,可以判断该功能似乎支持 .NET Core 3.1 或更高版本(包括 .NET 6)。我不确定它是否适用于 Framework 或早期的 Core 版本。 - MarredCheese
1
对于那些像我一样苦于找不到发布配置文件的人来说:在您第一次发布之后,该文件将在“Profiles > PublishProfiles”文件夹下创建,文件名为“FolderProfile.pubxml”。 - undefined
谢谢。我之前在我的配置文件中有这个设置,然后我更换了服务器,不得不重新构建配置文件,这时我丢失了这个设置并且忘记了它的具体内容。我发布到了暂存环境,发现它连接到了生产数据库。我已经修复了这个问题。 - undefined

26

您可以通过以下方式,将所需的ASPNETCORE_ENVIRONMENT作为参数传递给dotnet publish命令:

/p:EnvironmentName=Staging

例如:

dotnet publish /p:Configuration=Release /p:EnvironmentName=Staging
这将生成包含项目所需环境的正确配置信息的web.config文件:
<environmentVariables>
  <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>

22

编辑:自从RC2和RTM版本发布以来,此建议已过时。在版本发布中,我发现实现此目的的最佳方法是编辑每个环境中IIS的以下web.config部分:

system.webServer/aspNetCore

编辑environmentVariable条目并添加环境变量设置:

ASPNETCORE_ENVIRONMENT<您的环境名称>


作为drpdrp方法的替代方案,您可以执行以下操作:

  • 在project.json中,添加传递ASPNET_ENV变量直接给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"
    }
    
  • 发布时,请使用--iis-command选项指定环境:

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

    我发现这种方法比创建额外的IIS用户更不会打扰。


13
如果您正在通过Visual Studio的msdeploy发布,请在.pubxml文件中添加<IISCommand>Staging</IISCommand>,即可使用指定的IIS命令进行部署,即使您无法在发布UI中指定它。 - Dean North
@DeanNorth - 这非常棒!!像大将一样有效!感谢分享! - S. Rasmussen

18

我的Web应用(生产,暂存,测试)托管在IIS Web服务器上。因此,无法依赖于ASPNETCORE_ENVIRONMENT操作系统环境变量,因为将其设置为特定值(例如STAGING)会影响其他应用程序。

为了解决这个问题,我在Visual Studio解决方案中定义了一个自定义文件(envsettings.json):

enter image description here

文件内容如下:

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

然后,根据我的应用类型(生产、暂存或测试),我相应地设置这个文件:假设我正在部署测试应用程序,则会有:

"ASPNETCORE_ENVIRONMENT": "Test"
在Program.cs文件中,只需检索此值,然后设置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();
        }
    }

请在发布选项(project.json)中包含envsettings.json:

  "publishOptions":
  {
    "include":
    [
      "wwwroot",
      "Views",
      "Areas/**/Views",
      "envsettings.json",
      "appsettings.json",
      "appsettings*.json",
      "web.config"
    ]
  },
此解决方案使我能够在同一IIS上托管ASP.NET CORE应用程序,而不受环境变量值的影响。

非常好,我唯一建议的更改是交换 var currentDirectoryPath = Directory.GetCurrentDirectory(); 和 var currentDirectoryPath = PlatformServices.Default.Application.ApplicationBasePath; 这是获取当前目录的更安全的方式。 - Peter Kottas
11
当你不得不创建另一层配置来管理框架配置时,这是一个很棒的开箱即用体验。 - Kugel
1
“因此,无法依赖于ASPNETCORE_ENVIRONMENT操作系统环境变量”这种说法可能是不正确的。每个应用程序都有自己的池,因此您可以为每个应用程序设置环境,没有任何阻止的因素。 - makinyelure

18

除了上述选项之外,还有一些其他解决方案可与自动化部署很好地配合使用或需要更少的配置更改。

1. 修改项目文件(.CsProj)文件

MSBuild支持EnvironmentName属性,可以帮助设置正确的环境变量以便您希望部署的环境。环境名称将在发布阶段添加到web.config中。

只需打开项目文件(*.csProj)并添加以下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>
以上代码将在Debug配置下或未指定任何配置时,在生成的web.config文件中添加环境名称为Development。对于其他任何配置,生成的web.config文件中的环境名称都将为Production。更多详情在这里 2. 在发布配置文件中添加EnvironmentName属性。我们也可以在发布配置文件中添加<EnvironmentName>属性。打开位于Properties/PublishProfiles/{profilename.pubxml}的发布配置文件。这将在项目发布时设置web.config中的环境名称。更多详情在这里
<PropertyGroup>
  <EnvironmentName>Development</EnvironmentName>
</PropertyGroup>

3. 使用 dotnet publish 的命令行选项

此外,我们可以将属性EnvironmentName作为命令行选项传递给dotnet publish命令。以下命令将在web.config文件中包含环境变量Development

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


这似乎在 .net core 3.1 中不起作用,对我来说仍然没有设置。 - c-sharp-and-swiftui-devni
@rouge39nin - 我测试过了,在 .net core 3.1 中可以正常工作。您能否提供更多细节,说明您尝试了什么以及您的托管方法是什么? - Abhinav Galodha

16

通过广泛使用谷歌搜索,我找到了一个可行的解决方案,它由两个步骤组成。

第一步是将系统范围内的环境变量ASPNET_ENV设置为Production并重新启动Windows Server。之后,所有Web应用程序的EnvironmentName都将获得值“Production”。

第二步(启用暂存Web的值“Staging”)要更难才能正确工作,但这里有:

  1. 在服务器上创建新的Windows用户,例如StagingPool
  2. 为此用户创建新的用户变量ASPNETCORE_ENVIRONMENT,并将值设置为“Staging”(您可以通过以此用户身份登录或通过regedit完成)
  3. 作为管理员返回IIS管理器,在Staging Web正在运行的应用程序池下找到Identity,并将其设置为用户StagingPool
  4. 还要将Load User Profile设置为true,以便加载环境变量。 <- 非常重要!
  5. 确保StagingPool具有对Web文件夹的访问权限,并停止和启动应用程序池。

现在,暂存Web应该将EnvironmentName设置为“Staging”。

更新:在Windows 7+中,有一个命令可以从CMD提示符为指定的用户设置环境变量。 这会输出帮助和示例:

>setx /?

1
在ASP.NET 5 RC1中,环境变量已更改为Hosting:Environment。 - Grady Werner
当我们将其部署到Azure Web应用程序时,如何将“Load User Profile”设置为true? - GeekzSG
据我所知,在Azure门户中,对于Web应用程序有一个名为“应用设置”的部分,您可以在其中设置环境的键/值对:https://azure.microsoft.com/zh-cn/documentation/articles/web-sites-configure/ @PunitGanshani - drpdrp
1
@b.pell 看起来现在是 ASPNETCORE_ENVIRONMENT :) - Mark G
谢谢提醒。我们正在撰写过程中进行RC2的转换。 - b.pell
显示剩余2条评论

8

和其他答案类似,我希望确保我的ASP.NET Core 2.1环境设置在部署后仍然存在,但也只适用于特定的网站。

根据微软的文档,在IIS 10中可以使用以下PowerShell命令在应用程序池上设置环境变量:

$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

很不幸,我仍然不得不使用IIS 8.5,并认为自己没有机会。然而,仍然有可能运行简单的PowerShell脚本来为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 }

8

在@tredder的回答基础上,您可以使用appcmd更改environmentVariables。

Staging

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

生产

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


以下是如何在没有安装IIS的构建服务器上使用Powershell完成相同任务的方法。https://gist.github.com/markarnott/c4aec1fc544fe89e2bd21f3f00d78933 - Mark Arnott
指定“staging.example.com”或“example.com”将仅将该变量应用于这些特定的网站。省略它将为服务器上的所有网站创建全局变量。 - deadlydog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接