Специфические для приложения файлы app.config/web.config в Visual Studio

У нас есть несколько проектов .NET, где мы сохраняем определенные настройки в файлах конфигурации. Теперь у каждого разработчика будут свои собственные конфигурационные файлы, которые немного отличаются (разные строки подключения для подключения к локальной базе данных, разные конечные точки WCF и т.д.).

В настоящий момент мы склонны проверять файлы app/web.config и изменять их в соответствии с нашими потребностями. Это приводит к множеству проблем, так как время от времени кто-то проверяет собственные настройки или освобождает пользовательскую конфигурацию при получении последней версии от tfs.

Мой вопрос: как вы справляетесь с подобными ситуациями? Или у вас вообще нет этой проблемы?

Ответ 1

Мы используем систему, которая объединяет несколько существующих ответов на этой странице, плюс рисует это предложение Скотта Гензельмана.

Короче говоря, мы сделали, чтобы иметь общий файл app.config/web.config и иметь большинство конкретных настроек в отдельных файлах, как это предложено другими ответами здесь. например для наших настроек SMTP, app.config содержит

<system.net>
  <mailSettings>
    <smtp configSource="config\smtp.config" />
  </mailSettings>
</system.net>

Этот файл есть в исходном элементе управления. Однако отдельные файлы, например, не являются:

<?xml version="1.0" encoding="utf-8" ?>
<smtp deliveryMethod="Network">
  <network host="127.0.0.1" port="25" defaultCredentials="false" password="" userName ="" />
</smtp>

Это не совсем то, где история заканчивается. Что можно сказать о новых разработчиках или установке нового источника? Основная часть конфигурации больше не находится в контроле источника, и больно вручную собрать все необходимые им файлы .config. Я предпочитаю иметь источник, который, по крайней мере, будет компилироваться прямо из коробки.

Поэтому мы сохраняем версию файлов .config в исходном элементе управления с именами .config.default. Поэтому новое дерево источников выглядит следующим образом:

alt text

Тем не менее, на самом деле это не очень полезно для разработчиков, поскольку в Visual Studio это просто бессмысленные текстовые файлы. Следовательно, командный файл copy_default_config.bat заботится о создании исходного набора файлов .config из файлов .config.default:

@echo off
@REM Makes copies of all .default files without the .default extension, only if it doesn't already exist. Does the same recursively through all child folders.
for /r %%f in (*.default) do (
    if not exist "%%~pnf" (echo Copying %%~pnf.default to %%~pnf & copy "%%f" "%%~pnf" /y)
)
echo Done.

script безопасно перезапускается, поскольку разработчики, у которых уже есть файлы .config, не будут перезаписываться. Следовательно, можно было бы запустить этот командный файл как событие предварительной сборки. Значения в файлах .default могут быть не совсем корректными для новой установки, но они являются разумной отправной точкой.

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

alt text

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

Ответ 2

Здесь представлено решение для файлов web.config и Visual Studio 2010:

1) Измените вручную файл .csproj вашего веб-приложения, чтобы добавить AfterBuild Target, как это:

  <Project>
   ...
    <Target Name="AfterBuild">
      <Copy SourceFiles="web.config" DestinationFiles="obj\$(Configuration)\tempweb.config" />
      <TransformXml Source="obj\$(Configuration)\tempweb.config"
                  Transform="web.$(USERNAME).config"
                  Destination="obj\$(Configuration)\tempweb2.config" />
      <ReadLinesFromFile File="obj\$(Configuration)\tempweb2.config"><Output TaskParameter="Lines" ItemName="TransformedWebConfig"/></ReadLinesFromFile>
      <ReadLinesFromFile File="web.config"><Output TaskParameter="Lines" ItemName="UnTransformedWebConfig"/></ReadLinesFromFile>
      <Copy Condition=" @(UnTransformedWebConfig) != @(TransformedWebConfig) " SourceFiles="obj\$(Configuration)\tempweb2.config" DestinationFiles="web.config" OverwriteReadOnlyFiles="True" />
    </Target>
  </Project>

Эта цель преобразует файл Web.config, соответствующий текущему разработчику, - следовательно, переменную $(USERNAME) -, с соответствующим файлом, созданным в 1). Он заменит локальный Web.config только в том случае, если содержимое было изменено (чтобы избежать перезапуска) в каждой сборке, даже если локальный Web.config контролируется источником, поэтому для параметра OverwriteReadOnlyFiles установлено значение True. Этот факт на самом деле спорный.

2) Создайте файл с именем Web.[developer windows login].config для каждого разработчика в проекте. (например, на следующих скриншотах у меня есть два разработчика с именем smo и smo2):

enter image description here

Эти файлы (1 на разработчика) могут/должны контролироваться исходным кодом. Они не должны быть помечены как зависящие от основного Web.config, потому что мы хотим иметь возможность их индивидуально проверять.

Каждый из этих файлов представляет собой преобразование, применимое к основному файлу Web.Config. Синтаксис преобразования описан здесь: Синтаксис преобразования Web.config для развертывания проекта веб-приложений. Мы повторно используем эту классную задачу преобразования файлов Xml, которая поставляется в комплекте с Visual Studio. Цель этой задачи - объединить элементы и атрибуты Xml вместо перезаписи всего файла.

Например, вот пример web.[dev login].config, который изменяет строку соединения с именем "MyDB", независимо от остальной части файла Web.config:

<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
    <connectionStrings>
      <add name="MyDB" 
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
    </connectionStrings>
</configuration>

Теперь это решение не идеально, потому что:

  • после создания, разработчики могут иметь другой Web.Config локально, чем в исходной системе управления.
  • им может потребоваться принудительная локальная запись при получении нового Web.Config из исходной системы управления
  • разработчикам не следует проверять/в главном web.config. Он должен быть зарезервирован для нескольких человек.

Но по крайней мере вам нужно только сохранить уникальный основной файл web.config и один файл преобразования для каждого разработчика.

Аналогичный подход может быть применен для файлов App.config(а не в Интернете), но я не уточнил далее.

Ответ 3

В вашем Web.config используйте источник из других файлов

<configuration>
    <connectionStrings configSource="ConnectionStrings.config" />
...
</configuration>

Храните файл web.config в управлении версиями и не делайте этого для ConnectionStrings.config. Теперь у всех разработчиков есть один файл для строки подключения.

Вы можете сделать это для всех локальных зависимостей.

Ответ 4

Мы используем machine.config, чтобы избежать различий в web.config между средами.

Ответ 5

Игнорировать файлы и иметь Commom_Web.Config и Common_App.Config. Использование сервера построения непрерывной интеграции с задачами сборки, которые переименовывают эти два в обычные имена, чтобы сервер сборки мог выполнять свою работу.

Ответ 6

Как насчет игнорирования файла, поэтому он никогда не проверяется? Я столкнулся с аналогичной проблемой и добавил web.config в список игнорирования в Subversion.

Однако в TFS это немного сложнее, см. этот пост о том, как это сделать.

Ответ 7

Один из способов, которым вы могли бы справиться, - это иметь токенизированную систему и использовать грабли script для изменения значений.

Более рудиментарным методом может быть ссылка на файл AppSettings.config для всех приложений AppSettings в вашем web.config(аналогично соединениям), т.е.

<appSettings configSource="_configs/AppSettings.config" />

Затем у вас есть папка, в которой каждый из ваших разработчиков имеет версию в подпапке (то есть /_configs/dave/). Затем, когда разработчик работает над своим собственным кодом, они копируют из подпапки в корень связанной папки.

Вам нужно будет убедиться, что вы сообщаете об изменениях в этих файлах (если вы не указали). Если вы сохраняете файл AppSettings.config вне контроля источника и проверяете только отдельные папки разработчиков (все они), то они будут вынуждены скопировать правильный.

Я предпочитаю токенизацию, но могу быть более жестким, чтобы вставать и работать, если это предназначено только для быстрого исправления.

Ответ 8

У нас та же проблема, и мы делаем это

  • Проверьте в web.config значения testerver/production
  • Разработчик переходит в Windows Explorer и меняет режим только для чтения файла
  • Отредактируйте конфигурацию в соответствии с их окружением.
  • Регистрация в файле web.config происходит только при изменении значений развертывания или добавлении или удалении любой записи конфигурации.
  • Для каждой записи конфигурации требуется хороший комментарий, так как каждый dev должен быть изменен.

Ответ 9

Предполагая, что вы используете Visual Studio, почему бы вам не использовать разные конфигурации решений? Например: вы можете иметь конфигурацию Debug, которая использует Web.config.debug и конфигурацию Release, которая использует Web.config.release. Web.config.debug должен иметь что-то вроде

<appSettings file="C:/Standard_Path_To_Configs/Standard_Name_For_Config.config"> 

с файлом Standard_Name_For_Config.config, который содержит все персональные настройки разработчика, а в Web.config.release всегда есть производственные настройки. Вы можете хранить конфигурации по умолчанию в некоторой папке с контролируемым источником и заставлять нового пользователя отбирать их оттуда.