发布到IIS,设置环境变量

通过阅读这两个问题/答案,我可以在IIS 8.5服务器上运行ASP.NET 5应用程序。

ASP.NET vNext早期测试版发布到Windows Server中的IIS

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

问题是,即使在IIS上运行,Web应用程序仍在使用env.EnvironmentName,其值Development

此外,我想在同一服务器上运行同一Web的两个版本(暂存、生产),因此我需要一个方法来分别为每个Web设置变量。

这个怎么做?

164344 次浏览

经过广泛的谷歌搜索,我找到了一个可行的解决方案,其中包括两个步骤。

第一步是将系统范围环境变量ASPNET_ENV设置为生产环境,并将_ABC_设置为0。在此之后,所有Web应用程序都将值“ Production ”设置为EnvironmentName.

第二步(为暂存Web启用“暂存”值)更难正常工作,但它是:

  1. 在服务器上创建新的Windows用户,例如Stagingpool
  2. 对于该用户,创建新的用户变量ASPNetCore_环境,其值为“ staging ”(您可以通过以该用户身份登录或通过regedit登录来完成)。
  3. 以管理员身份返回IIS管理器,找到运行临时Web的应用程序池,然后在“高级设置”中将“标识”设置为“用户Stagingpool ”。
  4. 同时将加载用户配置文件设置为真的,以便加载环境变量。
  5. 确保Stagingpool对Web文件夹具有访问权限,然后停止并启动应用程序池。

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

更新:在Windows 7+_中,ABC_0可以在CMD提示符下为指定用户设置环境变量。此输出帮助加样本:

>setx /?

编辑:从RC2和RTM版本开始,此建议已过时。我发现在发行版中实现这一点的最佳方法是在IIS中为每个环境编辑以下web.config部分:

system.webServer/aspNetCore

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

ASPNETCORE_ENVIRONMENT< Your environment name >


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

  • project.JSON中,添加将ASPNET_环境变量直接传递给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"
    }
    
  • When publishing, use the --iis-command option to specify an environment:

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

I found this approach to be less intrusive than creating extra IIS users.

这个答案最初是为ASP.NET核心RC1编写的。在RC2中,ASP.NET核心从通用HttpPlaFrom处理程序移动到特定的AspNetCore处理程序。请注意,步骤3取决于您使用的ASP.NET核心的版本。

事实证明,可以设置ASP.NET核心项目的环境变量,而不必为用户设置环境变量或创建多个命令项。

  1. 转到IIS中的应用程序,然后选择“_ABC ” “_0 ”。
  2. 选择Configuration Editor
  3. 在“Section ”组合框中选择system.webServer/aspNetCore(RC2和RTM)或system.webServer/httpPlatform(RC1
  4. 在“From ”组合框中选择Applicationhost.config ...
  5. 右键单击enviromentVariables元素,选择'environmentVariables' element,然后Edit Itemsenter image description here
  6. 设置环境变量。
  7. 关闭窗口并单击“应用”。
  8. 完成

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

感谢Mark G和Tredder,针对RC2和RTM进行了更新。

使用<;AspNetCore>;下的<;环境变量>;部分更新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>

要扩展@tredder的回答,可以使用appcmd来更改环境变量。

分期

%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上的虚拟目录中有多个不同的应用程序,则可以使用具有编辑ApplicationHost.config的@Tredder解决方案。

我的情况是:

  • 我确实有API项目和应用程序项目,在同一个域下,放置在不同的虚拟目录中。
  • 根页面XXX似乎未将ASPNetCore_环境变量传播给其在虚拟目录和..中的子项。
  • ...我无法像@nickab描述的那样设置虚拟目录中的变量(在Configuration Editor中保存更改时,出现错误不支持该请求。(HRESULT异常:0x80070032)):
  • 进入ApplicationHost.config并手动创建节点,如下所示:

    <代码><;位置路径=“ XXX/app ”>; <;System.WebServer>; <;AspNetCore>; <;环境变量>; <;清除/>; <;环境变量name=“ AspNetCore_环境” value=“暂存”/>; <;/环境变量>; <;/aspnetcore>; <;/system.webserver>; <;/位置>; <;位置路径=“ XXX/API ”>; <;System.WebServer>; <;AspNetCore>; <;环境变量>; <;清除/>; <;环境变量name=“ AspNetCore_环境” value=“暂存”/>; <;/环境变量>; <;/aspnetcore>; <;/system.webserver>; <;/位置>;

重新启动IIS就完成了任务。

我将我的Web应用程序(生产、暂存、测试)托管在IIS Web服务器上。因此,不可能依赖AspNetCore_环境Operative的系统环境变量,因为将其设置为特定值(例如staging)会影响其他应用程序。

作为变通方法,我在VisualStudio解决方案中定义了一个自定义文件(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();
}
}

请记住在PublishOptions(project.JSON)中包含envSettings.JSON:

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

这个解决方案使我可以自由地将ASP.NET核心应用程序托管在相同的IIS上,而不受环境变量值的影响。

你需要知道的一个地方:

  • 对于要覆盖任何配置设置的环境变量,必须使用ASPNETCORE_作为前缀。
  • 如果要匹配JSON配置中的子节点,请使用:作为分隔符。如果平台不允许在环境变量键中使用冒号,请改用__
  • 您希望您的设置以ApplicationHost.config结束。使用IIS配置编辑器将导致您的输入被写入到应用程序的Web.config中,并将被下一次部署覆盖。
  • 要修改ApplicationHost.config,您需要使用appcmd.exe来确保所做的修改是一致的。示例:%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

  • 非URL安全的字符可以转义为Unicode,如%u007b表示左花括号。

  • 要列出当前设置(与web.config中的值组合),请执行以下操作:%systemroot%\system32\inetsrv\appcmd.exe list config "Default Web Site/MyVirtualDir" -section:system.webServer/aspNetCore
  • 如果多次运行该命令为同一个密钥设置配置密钥,则会多次添加该密钥。要删除现有值,请使用类似于%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的命令。

为了获得有关错误的详细信息,我不得不为相应的应用程序池添加_ABC_0环境变量system.applicationHost/applicationPools

注意:在我的例子中,Web应用程序是ASP.NET Core 2 Web应用程序,托管在IIS 10上。可以通过IIS Manager中的Configuration Editor来完成此操作(请参阅使用配置编辑器编辑集合,以了解在IIS Manager中查找此编辑器的位置)。

我已经使用web.config中的环境配置创建了一个用于发布IIS的存储库。

https://github.com/expressiveco/aspnetcorewebconfigforenvironment.

  • 设置
    • 将.csproj和.user.csproj文件中的节获取到项目文件中。
    • 获取MyAspNetEnvironment.props、Web.development.config和Web.production.config文件。
  • 配置
    • 相应地更改user.csproj中的“ AspNetCore_环境”属性的值。

与其他答案类似,我想确保我的ASP.NET Core 2.1环境设置在部署中保持不变,但也只应用于特定站点。

根据Microsoft的文档,可以在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_环境设置特定于站点的环境变量值:

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 }

您也可以使用以下命令将所需的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>

除了上面提到的选项之外,还有其他几个解决方案可以很好地进行自动部署,或者需要较少的配置更改。

修改项目文件(.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>

以上代码将添加环境名称作为Development(用于调试配置或未指定配置)。对于任何其他配置,环境名称将_生成的Web.config文件中的ABC_1。更多详情在这里

在发布配置文件中添加EnvironmentName属性。

我们还可以在发布配置文件中添加<EnvironmentName>属性。打开位于Properties/PublishProfiles/{profilename.pubxml}中的发布配置文件。这将在发布项目时在web.config中设置环境名称。更多详情在这里

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

3.使用dotnet发布的命令行选项

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

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

我修改了答案,给出了@克里斯蒂安·德尔·比安科。我将.NET Core 2和Upper的进程更改为project.JSON文件,现在是绝对的。

  1. 首先,在根目录下创建appSettings.JSON文件。有了内容

      {
    // Possible string values reported below. When empty it use ENV
    variable value or Visual Studio setting.
    // - Production
    // - Staging
    // - Test
    // - Development
    "ASPNETCORE_ENVIRONMENT": "Development"
    }
    
  2. Then create another two setting file appsettings.Development.json and appsettings.Production.json with the necessary configuration.

  3. Add necessary code to set up the environment to Program.cs file.

    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. EnvSettings.JSON添加到。csproj文件中,以便复制到已发布的目录。

       <ItemGroup>
    <None Include="envsettings.json" CopyToPublishDirectory="Always" />
    </ItemGroup>
    
  5. Now just change the ASPNETCORE_ENVIRONMENT as you want in envsettings.json file and published.

我知道已经给出了很多答案,但在我的例子中,我在项目中添加了web.{environment}.config版本,当为特定环境发布时,该值会被替换。


例如,对于暂存(web.staging.config)

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location>
<system.webServer>
<aspNetCore>
<environmentVariables xdt:Transform="InsertIfMissing">
<environmentVariable name="ASPNETCORE_ENVIRONMENT"
value="Staging"
xdt:Locator="Match(name)"
xdt:Transform="InsertIfMissing" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</location>
</configuration>

对于发布或生产,我将这样做(web.release.config)

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<location>
<system.webServer>
<aspNetCore>
<environmentVariables xdt:Transform="InsertIfMissing">
<environmentVariable name="ASPNETCORE_ENVIRONMENT"
value="Release"
xdt:Locator="Match(name)"
xdt:Transform="InsertIfMissing" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</location>
</configuration>

然后在发布时,我将选择或设置环境名称。这将替换最终Web.config文件中的环境的值。

对于那些希望在Azure DevOps管道中实现这一点的人来说,这可以通过添加目标计算机上的PowerShell任务并运行以下脚本来实现:

$envVariables = (
@{name='VARIABLE1';value='Value1'},
@{name='VARIABLE2';value='Value2'}
)


Set-WebConfigurationProperty -PSPath IIS:\ -Location $('mySite') -Filter /system.webServer/aspNetCore/environmentVariables -Name . -Value $envVariables

只需将<EnvironmentName>添加到您的发布配置文件:

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

该信息被复制到Web.config。(不要手动设置Web.config,因为它会被覆盖。)

来源:_农行_0