Здесь мы не будем останавливаться на подробном изучении файла web.config и для чего он предназначен. С данным материалом можно ознакомиться в соответствующем уроке.
Рассмотрим самый частый пример – строки подключения к базе данных. Локально мы работаем с одной базой, а после релиза база данных уже не тестовая, а боевая, на другом сервере. Соответственно, и настройки подключения к разным базам данных будут разные.
Другой пример. Обработка ошибок в приложении. Элемент:
<customErrors mode="Off/On" />
В процессе разработки нам важно знать, какие именно ошибки возникают и как их починить. В то же время, на продакшене такое поведение недопустимо, пользователь сайта не должен догадываться, что именно не работает, ему достаточно показать красивую страницу с кодом ошибки.
Перечислим наиболее частые ситуации, где имеются разные конфигурации для dev-а и для релиза.
- Строки подключения к базе данных
- Обработка ошибок в приложении
- Удалить атрибут debug при публикации проекта
- Отключение/включение кеширования контента
- HTTP-header’s ответа сервера
- Настройки в секции appSettings
- Любые другие индивидуальные настройки в проекте
Все эти настройки можно описать для трансформации файла web.config. Давайте посмотрим как.
В любом MVC-проекте файл web.config представляет собой группу, которая объединяет еще два файла: Web.Debug.config и Web.Release.config. Как раз в этих файлах и будут определяться настройки соответственно для дебага и для релиза. Если стандартных двух конфигураций недостаточно, то можно создать и новые, например, для другого тестового сервера:
- В меню Visual Studio пункт Build -> Configuration Manager…
В меню Visual Studio пункт Build -> Configuration Manager…
- Создаем новую конфигурацию
Создаем новую конфигурацию
- В контекстном меню файла web.config добавляем трансформацию для нового конфига
добавляем трансформацию для нового конфига
После подготовки всех конфигураций можно приступить непосредственно к разделению настроек. Посмотрим, как это работает.
По сути, файл трансформации представляет собой обычный XML-документ, где указаны изменения, которые будут применены при публикации проекта. По умолчанию здесь уже добавлены комментарии разработчиков для быстрого старта.
Представим, что нам для релизной версии проекта нужны следующие изменения и изменим файл Web.Release.config таким образом:
<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings xdt:Transform="Replace">
<remove name="LocalSqlServer" />
<add name="LocalSqlServer" providerName="System.Data.SqlClient" connectionString="Data Source=222.222.222.222; Database=DailyNews; Persist Security Info=true; User ID='user1'; Password='pass1';MultipleActiveResultSets=True" />
</connectionStrings>
<appSettings>
<add key="keyNew" value="valueNew" xdt:Locator="Condition(@key='keyOld')" xdt:Transform="Replace"/>
</appSettings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<customErrors mode="On" xdt:Transform="SetAttributes" />
</system.web>
<projectCustomSettings>
<email contactEmail="client@email.com" xdt:Transform="SetAttributes" />
</projectCustomSettings>
</configuration>
Обратим внимание на следующие моменты:
Для файла определено пространство имен XML-Document-Transform. Оно определяет всего два атрибута: Locator и Transform. С их помощью мы и будем нужным нам образом трансформировать конфиг-файл.
Посмотрим, что мы определили для трансформации.
- Мы полностью заменяем секцию connectionStrings. На продакш-сервере у нас будет одна строка подключения со стандартным названием . В ней прописаны актуальные для сервера настройки подключения к БД. Для атрибута Transform указано значение "Replace". Атрибут Locator здесь необязателен, так как мы работаем с целой секцией, и она может быть определена в конфиге лишь один раз.
- В секции appSettings мы находим элемент под ключом keyOld и заменяем его на новый элемент с новым ключом и с новым значением.
xdt:Locator="Condition(@key='keyOld')"
xdt:Transform="Replace" - В секции compilation мы удаляем из релиза атрибут debug
xdt:Transform="RemoveAttributes(debug)" - Выключаем детальную информацию об ошибках приложения. В секции customErrors меняем значение Off на On
xdt:Transform="SetAttributes" - Также у нас в приложении определены специфичные настройки. Наше приложение умеет отсылать письма на определенный ящик. Меняем тестовый ящик на актуальный адрес клиента. Трансформируем секцию email и атрибут contactEmail
xdt:Transform="SetAttributes"
Теперь опубликуем проект и посмотрим на release-версию файла Web.config
Полный список всех настроек для атрибутов Locator и Transform можно найти в официальной документации:
https://msdn.microsoft.com/ru-ru/library/dd465326(v=vs.100).aspx
При трансформации файла web.config важно понимать следующие моменты:
- Мы определяем, ЧТО мы хотим изменить и КАК мы хотим изменить. Используем для этого атрибуты Locator(что) и Transform(как)
- Файл трансформации не подменяет настоящий web.config файл, а лишь вносит в него указанные изменения в момент построения итогового файла в процессе публикации. То есть содержимое файла трансформации не равно содержимому файла web.config
- Трансформация происходит не в процессе разработки и компиляции проекта, а только в момент публикации
Что касается пункта 3 выше, то это стандартное поведение трансформера по задумке разработчиков, то есть трансформируем при публикации. Однако иногда возникают ситуации, когда трансформация удобна и в процессе разработки, подменить настройки при сборке проекта. Это можно сделать, внеся некоторые изменения в *.csproj файл проекта.
- Выгружаем наш проект из Visual Studio, если он на данный момент в работе
- Любым текстовым редактором открываем файл проекта _name_.csproj. Находим закомментированный участок кода, где предлагается внести свои изменения в процесс сборки проекта.
- Добавим свое правило для сборки проекта
<Target Name="BeforeBuild"> <TransformXml Source="Web.config" Transform="Web.$(Configuration).config" Destination="Web.config" /> </Target>
- Не забудьте сделать резервную копию оригинального файла web.config перед началом работы, чтобы не потерять настройки в процессе каждой сборки проекта.