Опубликовать в IIS, установив переменную среды

135

Прочитав эти два вопроса / ответа, я смог запустить приложение Asp.net 5 на сервере IIS 8.5.

Asp.net vNext: ранняя бета-версия публикации в IIS на сервере Windows

Как настроить приложение MVC6 для работы в IIS?

Проблема в том, что веб-приложение по-прежнему использует env.EnvironmentNameзначение Developmentдаже при запуске в IIS.

Кроме того, я хочу запустить две версии одной и той же сети (Staging, Production) на одном сервере, поэтому мне нужен метод для установки переменной для каждой сети отдельно.

Как это сделать?

drpdrp
источник
4
У одного обычно есть три сетевых среды: разработка, подготовка и производство. Веб-сервер находится в одной среде. Таким образом, установка переменной системной среды для сервера обычно не является настоящим ограничением. Можно по-прежнему использовать Properties\launchSettings.jsonдля моделирования другой среды для отладки в Visual Studio.
Олег

Ответы:

286

Этот ответ изначально был написан для ASP.NET Core RC1. В RC2 ASP.NET Core перешел с универсального обработчика httpPlafrom на специальный обработчик aspnetCore. Обратите внимание, что шаг 3 зависит от того, какую версию ASP.NET Core вы используете.

Оказывается, переменные среды для проектов ASP.NET Core можно устанавливать без необходимости устанавливать переменные среды для пользователя или создавать несколько записей команд.

  1. Зайдите в свое приложение в IIS и выберите Configuration Editor.
  2. Выбрать Configuration Editor
  3. Выберите system.webServer/aspNetCore(RC2 и RTM) или system.webServer/httpPlatform(RC1) в Sectionполе со списком
  4. Выберите Applicationhost.config ...в Fromполе со списком.
  5. Щелкните enviromentVariablesэлемент правой кнопкой мыши , выберите 'environmentVariables' element, затем Edit Items. введите описание изображения здесь
  6. Задайте переменные среды.
  7. Закройте окно и нажмите Применить.
  8. Готово

Таким образом, вам не нужно создавать специальных пользователей для вашего пула или создавать дополнительные записи команд в project.json. Кроме того, добавление специальных команд для каждой среды прерывает «сборку один раз, развертывание много раз», так как вам придется вызывать dnu publishотдельно для каждой среды вместо того, чтобы публиковать один раз и развертывать результирующий артефакт много раз.

Обновлено для RC2 и RTM благодаря Mark G и треддеру.

NickAb
источник
12
Для шага 3 я использовал system.webServer/aspNetCoreвместо этого.
Mark G
1
Переменные системной среды наследуются процессами при запуске. Поэтому, если вы измените какую-либо переменную env во время запуска вашего приложения, вы не сможете увидеть эти изменения по умолчанию. Чтобы изменения в системе env var вступили в силу, вам потребуется как минимум перезапустить сайт, возможно, пул или даже службу IIS, в зависимости от того, как IIS создает процессы. Это нужно проверить.
NickAb
7
Не будут ли удалены настройки, добавленные с помощью редактора конфигурации, при следующем развертывании?
Брэд Гарднер
11
@ brad-gardner, если изменения вносятся в Applicationhost.config вместо web.config, то изменения будут сохраняться между развертываниями.
NickAb
15
Работает для Asp.Net Core 2.0
Фрэнк Кэннон
35

Обновление web.config с <EnvironmentVariables> раздел под <aspNetCore>

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

Или, чтобы не потерять этот параметр при перезаписи web.config, внесите аналогичные изменения в applicationHost.config, указав расположение сайта, как предлагает @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
Это отличается тем, что ваш web.config является частью проекта и версируется в VCS. Если у вас несколько сред, таких как prod, staging, dev, вам понадобится способ трансформировать web.config для каждой из них. Изменение ApplicationHost.config в IIS влияет только на этот IIS. Таким образом, у вас может быть один web.config в вашей VCS и переменных среды, специфичных для IIS, которые переопределяют переменные web.config. ApplicationHost.config можно редактировать программно с помощью PowerShell iis.net/learn/manage/powershell/…
NickAb
Спасибо @NickAb, это избавляет от необходимости обновлять web.config при каждом развертывании. Я обновил свой ответ.
Trevor Daniels
У меня проблемы с выполнением этого из PowerShell. Я все время получаю Target configuration object '/system.webServer/aspNetCore/environmentVariables/environmentVariable is not found ... Обычно, чтобы установить некоторую переменную, я бы написал что-то вроде этого: Set-WebConfigurationProperty -PSPath IIS:\ -location example.com -filter /system.webServer/aspNetCore/environmentVariables/environmentVariable -name ASPNETCORE_ENVIRONMENT -value Staging что мне не хватает?
Christian
Я вернулся к тому, что знал и использовал appcmdвместо этого.
Christian
@Christian, ознакомьтесь с этим ответом: 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
21

Изменить: в выпусках RC2 и RTM этот совет устарел. Лучший способ, который я нашел для этого в выпуске, - это отредактировать следующие разделы web.config в IIS для каждой среды:

system.webServer/aspNetCore:

Отредактируйте запись environmentVariable и добавьте настройку переменной среды:

ASPNETCORE_ENVIRONMENT : < Your environment name >


В качестве альтернативы подходу 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.

Джошуа Бэррон
источник
11
Если вы публикуете через Visual Studio msdeploy. Затем вы можете поместить <IISCommand> Staging </IISCommand> в свой файл .pubxml, и он будет развернут с использованием указанной команды IIS, даже если вы не можете указать ее в пользовательском интерфейсе публикации.
Dean North
@DeanNorth - Это золото !! Работает как чемпион! Спасибо, что поделился!
С. Расмуссен
17

Мои веб-приложения (ПРОИЗВОДСТВО, ЭТАП, ТЕСТ) размещены на веб-сервере IIS. Таким образом, было невозможно полагаться на системную переменную среды оператора ASPNETCORE_ENVIRONMENT, потому что установка для нее определенного значения (например, STAGING) влияет на другие приложения.

В качестве обходного пути я определил собственный файл (envsettings.json) в моем решении visualstudio:

введите описание изображения здесь

со следующим содержанием:

{
  // 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();
        }
    }

Не забудьте включить envsettings.json в publishOptions (project.json):

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

Это решение позволяет мне размещать приложение ASP.NET CORE на одном и том же IIS, независимо от значения переменной окружения.

Кристиан Дель Бьянко
источник
Очень хорошо, единственное изменение, которое я предлагаю, - это swap var currentDirectoryPath = Directory.GetCurrentDirectory (); для var currentDirectoryPath = PlatformServices.Default.Application.ApplicationBasePath; Это гораздо более безопасный способ получить текущий каталог.
Питер Коттас
7
Какой замечательный опыт «из коробки», когда вам нужно создать еще один уровень конфигураций для управления конфигурациями фреймворка
Kugel
16

После обширного поиска в Google я нашел рабочее решение, которое состоит из двух шагов.

Первый шаг - установить общесистемную переменную среды ASPNET_ENV в значение «Производство» и перезапустить Windows Server. . После этого все веб-приложения получают значение «Производство» как EnvironmentName.

На втором этапе (чтобы включить значение Staging для промежуточной сети) было труднее заставить работать правильно, но вот оно:

  1. Создайте нового пользователя Windows, например StagingPool на сервере.
  2. Для этого пользователя создайте новую пользовательскую переменную ASPNETCORE_ENVIRONMENT со значением Staging (вы можете сделать это, войдя в систему как этот пользователь или через regedit)
  3. Вернувшись в качестве администратора в диспетчере IIS, найдите пул приложений, в котором работает промежуточный веб-сайт, и в расширенных настройках установите для идентификатора пользователя StagingPool .
  4. Также установите для параметра Load User Profile значение true , чтобы загружались переменные среды. <- очень важно!
  5. Убедитесь, что у StagingPool есть права доступа к веб-папке, а также к остановке и запуску пула приложений.

Теперь в промежуточной сети для EnvironmentName должно быть установлено значение «Staging».

Обновление: в Windows 7+ есть команда, которая может устанавливать переменные среды из командной строки CMD также для указанного пользователя. Это выводит справку плюс образцы:

>setx /?
drpdrp
источник
1
Похоже, что в ASP.NET 5 RC1 переменная среды была изменена на Hosting: Environment.
Grady Werner
Как установить для параметра «Загрузить профиль пользователя» значение true при его развертывании в веб-приложении Azure?
Puneet Ghanshani
@PunitGanshani Насколько я понимаю, на портале Azure
drpdrp
@GradyWerner Для RC2 они меняют его (на данный момент) на ASPNET_ENVIRONMENT ;-)
b.pell
1
@ b.pell Похоже, теперь это ASPNETCORE_ENVIRONMENT :)
Mark G
11

В качестве альтернативы вы можете передать желаемое ASPNETCORE_ENVIRONMENTв команду публикации dotnet в качестве аргумента, используя:

/p:EnvironmentName=Staging

например:

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

Это сгенерирует web.config с правильной средой, указанной для вашего проекта:

<environmentVariables>
  <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Staging" />
</environmentVariables>
Шелдон Нуньес
источник
9

Помимо упомянутых выше вариантов, есть несколько других решений, которые хорошо работают с автоматическим развертыванием или требуют меньшего количества изменений конфигурации.

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>

В приведенном выше коде будет добавлено имя среды, как Developmentдля конфигурации отладки, или если конфигурация не указана. Для любой другой конфигурации имя среды будет Productionв сгенерированном файле web.config. Подробнее здесь

2. Добавление свойства EnvironmentName в профили публикации.

Мы также можем добавить <EnvironmentName>свойство в профиль публикации. Откройте файл профиля публикации, который находится в папке. Properties/PublishProfiles/{profilename.pubxml}Это установит имя среды в web.config при публикации проекта. Подробнее здесь

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

3. Параметры командной строки с использованием dotnet publish

Кроме того, мы можем передать свойство EnvironmentNameкак параметр командной строки dotnet publishкоманде. Следующая команда будет включать переменную среды, как Developmentв файле web.config.

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

Абхинав Галодха
источник
7

Чтобы расширить ответ @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

Кристиан
источник
Вот как сделать то же самое с Powershell на сервере сборки без установленного IIS. gist.github.com/markarnott/c4aec1fc544fe89e2bd21f3f00d78933
Марк Арнотт
Если указать staging.example.com или example.com, переменная будет применяться только к этим конкретным веб-сайтам. Если пропустить это, будет создана глобальная переменная для всех веб-сайтов на сервере.
deadlydog
6

Что нужно знать в одном месте:

  • Чтобы переменные среды переопределяли любые параметры конфигурации, они должны иметь префикс 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.
realMarkusSchmidt
источник
1
Обратите внимание, что /commit:siteизменения записаны в web.config, для того, чтобы сохранить их в ApplicationHost.configодном следует использовать/commit:apphost
Ангел Йорданов
-section:system.webServer/aspNetCore /-"environmentVariables.(с минусом для удаления переменной среды) не выполняется во время конвейера выпуска Azure. Ошибка есть hresult:80070032, message:Command execution failed. Однако clear config "Default Web Site/$(webSiteName)" -section:system.webServer/aspNetCore /commit:siteработает нормально. Он очищает весь раздел aspNetCore для веб-сайта, но это не проблема, так как он параметризуется во время выпуска.
олекса
6

Как и в других ответах, я хотел убедиться, что мой параметр среды ASP.NET Core 2.1 сохранялся во всех развертываниях, но также применялся только к определенному сайту.

Согласно документации Microsoft, можно установить переменную среды в пуле приложений, используя следующую команду PowerShell в 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

К сожалению, мне все еще приходится использовать 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 }
dasch88
источник
5

Решение @tredder с редактированием applicationHost.config - это то, что работает, если у вас есть несколько разных приложений, расположенных в виртуальных каталогах на IIS.

Мой случай:

  • У меня есть API проекта и APP проекта, в том же домене, размещенных в различных виртуальных каталогов
  • Корневая страница XXX , похоже, не передает переменную ASPNETCORE_ENVIRONMENT своим дочерним элементам в виртуальных каталогах и ...
  • ... Я не могу установить переменные внутри виртуального каталога, как описано в @NickAb (получена ошибка Запрос не поддерживается. (Исключение из HRESULT: 0x80070032) во время сохранения изменений в редакторе конфигурации):
  • Заходим в applicationHost.config и вручную создаем такие узлы:

    <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>

и перезапуск IIS выполнил свою работу.

Бартош Ленар
источник
0

Чтобы получить подробную информацию об ошибке, мне пришлось добавить ASPNETCORE_ENVIRONMENTпеременную среды для соответствующего пула приложений system.applicationHost/applicationPools .

Примечание: в моем случае ASP.NET Core 2веб-приложение было размещено на сервере IIS 10. Это можно сделать через Configuration Editorin IIS Manager(см. Редактирование коллекций с помощью редактора конфигурации, чтобы выяснить, где найти этот редактор IIS Manager).

Дмитрий Павлов
источник
0

Я создал репозиторий для публикации IIS с конфигурацией среды в Web.config.

https://github.com/expressiveco/AspnetCoreWebConfigForEnvironment

  • Настроить
    • Загрузите разделы из файлов .csproj и .user.csproj в файлы проекта.
    • Получите файлы MyAspNetEnvironment.props, web.development.config и web.production.config.
  • конфигурация
    • Измените значение свойства ASPNETCORE_ENVIRONMENT в user.csproj соответствующим образом.
subcoder
источник
Похоже, это не дает качественного ответа на вопрос. Измените свой ответ, добавив общие сведения об этом решении, или просто удалите его и опубликуйте в качестве комментария к вопросу. Спасибо!
sɐunıɔ ןɐ qɐp
0

Я изменил ответ, который дан @Christian Del Bianco . Я изменил процесс для .net core 2 и выше, поскольку теперь файл 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. Затем создайте еще два файла настроек appsettings.Development.json и appsettings.Production.json с необходимой конфигурацией.

  3. Добавьте необходимый код для настройки среды в файл 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. Добавьте envsettings.json в свой .csproj файл для копирования в опубликованный каталог.

       <ItemGroup>
            <None Include="envsettings.json" CopyToPublishDirectory="Always" />
        </ItemGroup>
    
  5. Теперь просто измените ASPNETCORE_ENVIRONMENT, как хотите, в файле envsettings.json и опубликуйте.

Md. Назрул Ислам
источник