Continuous Integration: Трансформация Web.config

4 мая 2013 г.

Скачать исходный код

Начнем рассмотрение работы с config-файлами с самой простой темы. Создадим приложение ASP.NET MVC 4. По-умолчанию в созданном проекте уже есть 2 конфигурации (Debug, Release) и 3 config-файла (Web.config, Web.Debug.config, Web.Release.config):

Сгенерированные файлы Web.Debug.config и Web.Release.config содержат немного полезного кода. Для демонстрации их возможностей добавим замену строки подключения к БД в разных конфигурациях сборки. Получим следующие файлы:

Web.config

...
  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcApplication-20130502094058;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MvcApplication-20130502094058.mdf" providerName="System.Data.SqlClient" />
  </connectionStrings>
...

Web.Debug.config

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
      <add xdt:Transform="Replace" xdt:Locator="Match(name)"
       name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-MvcApplication-20130502094058;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-MvcApplication-20130502094058.mdf" providerName="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

Web.Release.config

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <connectionStrings>
    <add xdt:Transform="Replace" xdt:Locator="Match(name)"
     name="DefaultConnection" connectionString="Data Source=10.10.0.1;Initial Catalog=ProductionDB;User Id=username; Password=password;" providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

Файлы конфигураций Web.Debug.config и Web.Release.config содержат схемы трансформации. В нашем случае мы будем трансформировать файл Web.config. С помощью xdt:Transform="Replace" поменяем значение атрибута connectionString.

Из примера видно, что для конфигурации Debug будет использоваться локальная БД. Конфигурация Release пойдет на боевой сервер, поэтому в строке подключения мы указали путь до БД MSSQL, с которой работают конечные пользователи.

Более подробно о синтаксисе трансформации можно прочитать на MSDN.

Target AfterBuild

Теперь сделаем автоматическую трансформацию Web.config во время сборки проекта. Для этого добавим вызов TransformXml в target AfterBuild нашего проекта:

MvcApplication.csproj:

...
  <Target Name="AfterBuild">
    <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" StackTrace="true" />
  </Target>
...

Если мы поменяем конфигурацию сборки на Release и сделаем Build проекта, то в файле Web.config получим следующее:

Как мы видим, наш файл Web.config был изменен. В строку подключения подставились данные из Web.Release.config. Если выставить конфигурацию Debug и сделать Build, то в строку подключения подставится значение из Web.Debug.config.

Использование трансформации при Deploy

При сборке проекта можно посмотреть Output:

...
1>  Configuration=Release
...
Target "AfterBuild" in project "..\MvcApplication\MvcApplication\MvcApplication.csproj" (target "Build" depends on it):
1>Using "TransformXml" task from assembly "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll".
1>Task "TransformXml"
1>  Transforming Source File: Web.config
1>    Applying Transform File: Web.Release.config
1>    Executing Replace (transform line 4, 10)
1>      on /configuration/connectionStrings/add[@name='DefaultConnection']
1>      Applying to 'add' element (source line 7, 6)
1>      Replaced 'add' element
1>    Done executing Replace
1>    Output File: Web.config
1>  Transformation succeeded
1>Done executing task "TransformXml".
1>Done building target "AfterBuild" in project "MvcApplication.csproj".
...

Получается, что для создания релиза, нам достаточно во время сборки проекта указать конфигурацию Release и к Web.config будет применена соответствующая трансформация.

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

Обратите внимание, что схему трансформации можно применять к любой секции config-файлов. Это могут быть appSettings, customErrors и другие. Замена строки подключения приведена, как самый наглядный и популярный пример.


Статья из серии Continuous Integration: Работа с Config-файлами:

  1. Continuous Integration: Трансформация Web.config
  2. Continuous Integration: Процесс сборки проекта и трансформации Config-файлов
  3. Continuous Integration: Создание собственной конфигурации
  4. Continuous Integration: Трансформация App.config
  5. Continuous Integration: Рефакторинг файлов конфигурации

9 комментариев:

  1. Отлично! Задумался об использовании.

    ОтветитьУдалить
  2. Александр,

    Что Вы делаете когда в release трансформации находятся production пароли которые не хотелось бы хранить вместе с исходным кодом?

    ОтветитьУдалить
  3. В любом случае их где-то надо хранить. Вы их в отдельном репозитории держите?

    ОтветитьУдалить
  4. Да, мы в отдельном.
    Процедура релиза состоит из 2-х шагов: build и deploy. На шаге deploy и накладываем трансформацию которая храниться в секретном репозитории

    ОтветитьУдалить
  5. Это интересно. Получается у вас не все имеют доступ к Deploy?
    Вы где-то описывали ваш процесс выпуска релиза? Я бы почитал :)

    ОтветитьУдалить
  6. У нас есть dev, stage, prod развертывания. Причем prod развертываний может быть несколько (грубо говоря под каждого клиента свое развертывание). Доступ открыт ко всем, кроме prod.
    Процедура выпуска нигде не описана, как будет время напишу и поделюсь ссылкой

    ОтветитьУдалить
  7. Добрый день!
    Александр,
    А что делать если у меня не вебконфиг а апп конфиг и виндовое приложение ? такой возможности там нет , как поступать в таком случае?

    ОтветитьУдалить
  8. Я как раз к следующей неделе пишу в цикл очередную статью Continuous Integration: Трансформация App.config


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

    ОтветитьУдалить
  9. Активно использую web.config transformation, однако тут есть один большой минус - трансформация возможна только при сборке приложения, а не при развёртывании. Таким образом невозможно использовать подход к деплою приложения на основе артифактов - уже собранных приложений. Почти все билд серверы (за исключением TFS) имеют возможность публиковать результаты сборки. На мой взгляд более верным является способ делать publish уже собранных сборок и уже потом делать трансформацию. В противном случае необходимо под каждое окружение делать отдельную сборку - qa, stage, live.

    ОтветитьУдалить

Моя книга «Антихрупкость в IT»

Как достигать результатов в IT-проектах в условиях неопределённости. Подробнее...