Файлы app.config / web.config для конкретных разработчиков в Visual Studio

93

У нас есть несколько проектов .NET, в которых мы храним определенные настройки в файлах конфигурации.

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

На данный момент мы стараемся проверять файлы app / web.config и изменять их в соответствии с нашими потребностями.

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

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

twarz01
источник
10
Я голосую за повторное открытие, поскольку это распространенная проблема для разработчиков Visual Studio и напрямую связана с инструментами, которые используют разработчики. (отсюда и голоса)
Кристиан Голлхардт 09
Согласны, это постоянная проблема, поскольку размер нашей команды вырос, а различные попытки решения были неудовлетворительными.
DiskJunky

Ответы:

66

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

Короче говоря, мы сделали общий 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 . Таким образом, свежее дерево исходного кода выглядит так:

альтернативный текст

Тем не менее, это бесполезно для разработчика, поскольку для 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.

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

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

альтернативный текст

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

Гэвин
источник
Почему бы не иметь в репозитории непосредственно основной .config, а не отдельные?
graffic
6
Какая боль, нам нужно лучшее решение для этого. У меня был подобный метод, и я устал от его хрупкости и необходимости объяснения новым разработчикам.
jpierson
@Gavin, я получаю сообщение об ошибке, если пытаюсь запустить указанный вами файл bat: '∩╗┐ @ echo' не распознается как внутренняя или внешняя команда, работающая программа или командный файл.
Остин
2
@Austin, у вас, кажется, есть какой-то непечатаемый мусор перед '@echo', часть которого, возможно, является меткой порядка байтов Unicode? Возможно, что-то пошло не так при копировании / вставке, или командный файл сохранен в кодировке, которая не может быть правильно прочитана.
Gavin
21

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

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

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

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

Филипе Пиньейру
источник
1
У меня это сработало. См. Также: davidgiard.com/2012/05/25/… Файл ConnectionStrings.config должен находиться в той же папке, что и приложение или веб-конфигурация. Кроме того, вы должны изменить его свойства на «копировать, если новее» для вывода. А файлу ConnectionStrings.config нужен полный раздел с открывающими и закрывающими элементами. Вы также должны установить контроль версий, чтобы игнорировать файл, поэтому каждый из них зависит от пользователя.
Джеффри Рафгарден
1
Я использовал параметр <appSettings file = "..">, так как мне пришлось объединить настройки
Spikolynn
1
@JeffreyRoughgarden Если вы включите файл ConnectionStrings.config в обозреватель решений, должен ли этот файл существовать в filesysterm? И если это так, это означает, что вы проверили его в системе контроля версий. Это первая проблема, от которой мы пытались уйти.
Jez
20

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

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

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

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

Эти файлы (по 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 (не для Интернета), но я не стал вдаваться в подробности.

Саймон Мурье
источник
Я переименовал свой Web.config в Web.base.config, создал новый файл Web.config, а затем изменил его с <Copy SourceFiles = "web.config"> на <Copy SourceFiles = "web.base.config" на шаге 1. Таким образом я могу получить локальный файл web.config, который можно игнорировать в системе управления версиями.
С. Багги
Это все еще не идеально, но я предпочитаю его другому решению
JMK
Как вы думаете, можно ли использовать, web.default.configкогда web.$(USERNAME).configне существует? Кстати, спасибо за отличный ответ.
Christian Gollhardt
2

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

Дарин Димитров
источник
14
предпочел бы избежать изменения machine.config
twarz01
0

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

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

Марко
источник
0

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

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

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

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

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

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

Искусственное золото
источник
0

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

Артис
источник
это нужно сделать на машинах разработчика, прежде чем он перейдет на сервер сборки
twarz01
Нет, это переименование не должно происходить на сервере сборки. Общие файлы конфигурации, хранящиеся в Subversion, не зависят от конкретного разработчика. В то время как каждый разработчик запускает свои персональные файлы конфигурации для разработки на своей машине и не заботится об их отправке, потому что это не часть подрывной деятельности.
Arthis
То, что он не поддерживает, - это отладка приложения разработчиками. Корень web.configв исходной папке используется во время отладки. Если вы, например, добавляется web.configк .gitignoreи либо требуется пользователям копировать Commom_Web.Configв web.configи редактировать их фантазии, вы часть пути. Но затем, когда вам нужно отредактировать что-то, что одинаково на всех машинах разработчика, например, system.web/compilationраздел или конкретный объект, appSettingsкоторый должен быть одинаковым везде, эта схема разваливается.
binki
0

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

  • Проверьте web.config со значениями testserver / production
  • Разработчик переходит в проводник Windows и меняет режим только для чтения файла
  • Отредактируйте конфигурацию в соответствии с их средой.
  • Регистрация в web.config происходит только при изменении значений развертывания или при добавлении или удалении любой записи конфигурации.
  • Это требует большого количества комментариев для каждой записи конфигурации, так как это должно быть изменено каждым разработчиком.
Джой Джордж Кунджиккуру
источник
1
Это может работать лучше в магазинах, где исходный элемент управления, который вы используете, по умолчанию устанавливает поля только для чтения, но для других, использующих Subversion, это также может не работать. Мы могли бы установить разрешения только на чтение в репозитории, чтобы предотвратить его фиксацию, однако это нужно будет установить для каждого файла конфигурации для каждой ветви.
jpierson
Для тех из нас, кто не использует что-то вроде TFS, не очевидно, как это решение может работать. Не могли бы вы дать еще немного предыстории? Кроме того, не требует ли от разработчиков быть внимательными и случайно не проверить файл?
binki
-1

Предполагая, что вы используете Visual Studio, почему бы вам не использовать разные конфигурации решения? Например: у вас может быть конфигурация отладки, которая использует Web.config.debug, и конфигурация выпуска, которая использует 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 всегда есть производственные настройки. Вы можете хранить конфигурации по умолчанию в какой-нибудь папке с исходным кодом и заставлять нового пользователя брать их оттуда.


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