Web Config Transform не работает - PullRequest
       92

Web Config Transform не работает

79 голосов
/ 12 января 2012

В приложении .NET MVC 3.0 у меня есть следующая конфигурация в appSettings:

web.config

<appSettings>
<add key="SMTPHost" value="mail.domain.com"/>
    <add key="SMTPUsername" value="user@gmail.com"/>
    <add key="SMTPPort" value="25"/>
    <add key="SMTPPwd" value="mypassword"/>
    <add key="EmailFrom" value="notific@gmail.com"/>
</appSettings>

Для отладки у меня определено следующее преобразование конфигурации:

web.Debug.config

<appSettings>
    <add  key="SMTPPort" value="58" xdt:Transform="Replace" xdt:Locator="Match(key)" />
</appSettings>

И я запускаю приложение в режиме отладки, но мой порт SMTP по-прежнему принимает значение из web.config, а не web.Debug.config.

Кто-нибудь может подсказать, что может быть не так в этой конфигурации?

Ответы [ 8 ]

142 голосов
/ 12 января 2012

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

Если вы хотите, чтобы это было выполнено как часть операции построения app.config, то вы можете использовать преобразования SlowCheetah - XMLПлагин Visual Studio:

http://visualstudiogallery.msdn.microsoft.com/69023d00-a4f9-4a34-a6cd-7e854ba318b5

23 голосов
/ 27 июня 2013

Visual Studio (2010 - 2017) к сожалению не напрямую поддерживает его во время отладки, он предназначен только для публикации - даже с расширением SlowCheetah (помеченный ответ) он не работает для меня (только для проектов, использующих app.config, а не web.config).

Обратите внимание , что существует обходной путь , описанный в codeproject .

В нем описано, как изменить файл .msproj для перезаписи текущего файла web.config преобразованной версией.

Сначала я опишу этот обходной путь как Вариант 1 , но недавно я обнаружил еще один Вариант 2 , который проще в использовании (так что вы можете перейти к варианту 2 напрямую если хотите):


Вариант 1: Я добавил инструкции, взятые из исходной статьи codeproject (см. Ссылку выше), потому что снимки экрана там уже пропали, а я нет хочу потерять всю информацию:

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

  • Во-первых, создайте необходимые конфигурации в VS.Net , предполагая, что отладки и выпуска по умолчанию недостаточно для того, что вы пытаетесь выполнить.
  • Щелкните правой кнопкой мыши на web.config и выберите Добавить преобразования конфигурации - это создаст зависимый конфигурационный файл преобразования для каждой из определенных вами конфигураций.
  • Теперь вы можете переименовать ваш web.config в web.base.config.
  • Добавьте web.config в ваш проект. Не имеет значения, что находится в нем, потому что оно будет перезаписываться каждый раз, когда мы делаем сборку, но мы хотим, чтобы это было частью проекта, поэтому VS.Net не дает нам "Ваш проект не настроен для отладки " всплывающее окно.
  • Отредактируйте .csproj Файл проекта и добавьте следующую задачу TransformXml к цели AfterBuild. Здесь вы можете видеть, что я буду преобразовывать файл web.base.config, используя web.[configuration].config, и он сохранит его как web.config. Для получения подробной информации, пожалуйста, проверьте это Microsoft Q & A, а для получения инструкций о том, как расширить сборку, посмотрите там .

Вариант 2:

На основании этого ответа я разработал простое консольное приложение TransformConfig.exe (в синтаксисе C # 6.0):

using System;
using System.Linq;
using Microsoft.Web.XmlTransform;

namespace TransformConfig
{

  class Program
  {
    static int Main(string[] args)
    {
        var myDocumentsFolder = $@"C:\Users\{Environment.UserName}\Documents";
        var myVsProjects = $@"{myDocumentsFolder}\Visual Studio 2015\Projects";

        string srcConfigFileName = "Web.config";
        string tgtConfigFileName = srcConfigFileName;
        string transformFileName = "Web.Debug.config";
        string basePath = myVsProjects + @"\";
        try
        {

            var numArgs = args?.Count() ?? 0;
            if (numArgs == 0 || args.Any(x=>x=="/?"))
            {
                Console.WriteLine("\nTransformConfig - Usage:");
                Console.WriteLine("\tTransformConfig.exe /d:tgtConfigFileName [/t:transformFileName [/s:srcConfigFileName][/b:basePath]]");
                Console.WriteLine($"\nIf 'basePath' is just a directory name, '{basePath}' is preceeded.");
                Console.WriteLine("\nTransformConfig - Example (inside PostBuild event):");
                Console.WriteLine("\t\"c:\\Tools\\TransformConfig.exe\"  /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config /b:\"$(ProjectDir)\\\"");
                Environment.ExitCode = 1;
                return 1;
            }

            foreach (var a in args)
            {
                var param = a.Trim().Substring(3).TrimStart();
                switch (a.TrimStart().Substring(0,2).ToLowerInvariant())
                {
                    case "/d":
                        tgtConfigFileName = param ?? tgtConfigFileName;
                        break;
                    case "/t":
                        transformFileName = param ?? transformFileName;
                        break;
                    case "/b":
                        var isPath = (param ?? "").Contains("\\");
                        basePath = (isPath == false)
                                    ? $@"{myVsProjects}\" + param ?? ""
                                    : param;
                        break;
                    case "/s":
                        srcConfigFileName = param ?? srcConfigFileName;
                        break;
                    default:
                        break;
                }
            }
            basePath = System.IO.Path.GetFullPath(basePath);
            if (!basePath.EndsWith("\\")) basePath += "\\";
            if (tgtConfigFileName != srcConfigFileName)
            {
                System.IO.File.Copy(basePath + srcConfigFileName,
                                     basePath + tgtConfigFileName, true);
            }
            TransformConfig(basePath + tgtConfigFileName, basePath + transformFileName);
            Console.WriteLine($"TransformConfig - transformed '{basePath + tgtConfigFileName}' successfully using '{transformFileName}'.");
            Environment.ExitCode = 0;
            return 0;
        }
        catch (Exception ex)
        {
            var msg = $"{ex.Message}\nParameters:\n/d:{tgtConfigFileName}\n/t:{transformFileName}\n/s:{srcConfigFileName}\n/b:{basePath}";
            Console.WriteLine($"TransformConfig - Exception occurred: {msg}");
            Console.WriteLine($"TransformConfig - Processing aborted.");
            Environment.ExitCode = 2;
            return 2;
        }
    }

    public static void TransformConfig(string configFileName, string transformFileName)
    {
        var document = new XmlTransformableDocument();
        document.PreserveWhitespace = true;
        document.Load(configFileName);

        var transformation = new XmlTransformation(transformFileName);
        if (!transformation.Apply(document))
        {
            throw new Exception("Transformation Failed");
        }
        document.Save(configFileName);
    }

  }
}

Убедитесь, что вы добавили DLL "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.XmlTransform.dll" в качестве ссылки (этот пример относится к VS 2015, для более старых версий замените v14.0 в пути на соответствующий номер версии, например, v11.0).

Для Visual Studio 2017, схема именования пути изменена: например, для корпоративной версии это здесь: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web.
Я предполагаю, что для профессиональной версии вам нужно заменить Enterprise в пути на Professional. Если вы используете предварительную версию, дополнительно замените 2017 на Preview.

Скомпилируйте его и поместите файл .exe в каталог, например, C:\MyTools\.

Использование: Вы можете использовать его в своем событии после сборки свойствах проекта , выберите События сборки , затем отредактируйте Командную строку события после сборки ). Параметры командной строки (пример):

"C: \ MyTools \ TransformConfig.Exe" /d:Web.config /t:Web.$(ConfigurationName).config /s:Web.Template.config / b: "$ (ProjectDir) \"

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

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

Создайте шаблон, просто скопировав исходный файл Web.config и назовите его Web.Template.config.

Примечание:

  • Если вы предпочитаете, вы также можете скопировать файл TransformConfig.exe в путь Visual Studio, упомянутый выше, где находится Microsoft.Web.XmlTransform.dll, и ссылаться на него во всех ваших проектах, где вам нужно преобразовать свои конфигурации.

  • Для тех из вас, кто интересуется, почему я добавил назначения Environment.ExitCode = x;: простой возврат int из Main не помог в событии build. Подробнее здесь.

  • Если вы публикуете свой проект и используете Web.Template.config, убедитесь, что вы выполнили rebuild в своем решении с правильной конфигурацией (обычно Release), прежде чем публиковать. Причина в том, что Web.Config перезаписывается во время отладки, и в противном случае вы можете преобразовать неправильный файл.

21 голосов
/ 21 января 2016

Ответ на ваш вопрос не прост, потому что это создает проблему - если вы хотите преобразовать Web.config с помощью Web.debug.config - где должен храниться эффект преобразования?В самом Web.config?Это перезапишет исходный файл преобразования!Вероятно, поэтому Visual Studio не выполняет преобразования во время сборки.

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

  1. Создание преобразований конфигурации для конфигураций (отладка, выпуск и т. Д.)
  2. Переименование Web.config файла в Web.base.config - преобразования должны автоматически переименовываться соответственно (Web.base.Debug.config и т. Д.)
  3. Добавитьследующий transformWebConfig.proj XML-файл в папку вашего проекта:
<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" DefaultTargets="TransformWebConfig" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
  <Target Name="TransformWebConfig">
    <TransformXml Source="Web.base.config" Transform="Web.base.$(CurrentConfig).config" Destination="Web.config" />
  </Target>
</Project>
Перейдите к свойствам вашего проекта, выберите События сборки и добавьте следующее содержимое в Командная строка события после сборки :
@if exist "%ProgramFiles(x86)%\MSBuild\12.0\bin" set PATH=%ProgramFiles(x86)%\MSBuild\12.0\bin;%PATH%
msbuild $(ProjectDir)transformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath)

Сейчас,при создании решения будет создан файл Web.config с допустимыми преобразованиями для активной конфигурации.

4 голосов
/ 01 июня 2017

На ваш немедленный вопрос дан ответ - объяснение состоит в том, что преобразование применяется при публикации, а не при сборке.

Однако я думаю, что оно не предлагает решения о том, как достичь того, чего вы хотитеdo.

Я уже несколько дней пытаюсь решить эту проблему, ища способ сохранить чистоту web.config и установить все ключи, которые различаются в зависимости от среды в соответствующих файлах преобразования.Я пришел к выводу, что самое простое и стабильное решение - использовать значения отладки в исходном файле web.config, чтобы они всегда присутствовали при выполнении отладки в Visual Studio.

Затем создайте преобразования для различных сред, которые вы хотите опубликовать - тестирование, интеграцию, производство - все, что у вас есть.Для этого будет достаточно встроенной функциональности для преобразования файлов web.config при публикации.Нет необходимости в SlowCheetah или редактировании событий сборки или файлов проекта.Если у вас есть только веб-проекты, которые есть.

Если вы хотите, у вас также может быть файл web.debug.config в вашем решении, просто для хранения отдельного файла со всеми значениями, относящимися к среде разработки.,Обязательно прокомментируйте в нем, что значения не применяются при запуске в Visual Studio, хотя, если кто-то еще попытается использовать его для этой цели!

3 голосов
/ 01 июня 2019

для VS 2017 Я нашел ответ здесь не уверен, почему никто не ссылался на него выше, поскольку это, кажется, очень популярное решение. Очень легко тоже. Убедитесь, что вы видите комментарий IOrlandoni от 5 марта 2019 года о том, что он работает в VS 2017 и во всех версиях.

В основном это два степпера. Сначала вы редактируете файл .csproj, добавляя код ниже. Во-вторых, вы создаете новую конфигурацию web.base.config и копируете туда существующий web.config. После этого любая сборка перезапишет ваш web.config с желаемым преобразованием.

    <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets" />
<Target Name="BeforeBuild">
  <TransformXml Source="Web.Base.config" Transform="Web.$(Configuration).config" Destination="Web.config" />
</Target>  
1 голос
/ 22 мая 2017

Используйте Octopus Deploy (версия для сообщества бесплатна) и дайте ему преобразовать web.config для вас.Шаги:

  1. Настройка Octopus для развертывания веб-приложения
  2. Убедитесь, что у вашего Web.Release.config свойство Build Action установлено на Content, какваш основной web.config файл.

Вот и все!Octopus сделает все остальное без какого-либо специального конфига.При развертывании веб-сайта IIS по умолчанию это будет сделано из коробки: enter image description here

0 голосов
/ 15 февраля 2018

Недавно у меня возникла та же проблема со старым web.config , основанным на .NET Framework 2.0. Решением было просто удалить пространство имен web.config ( xmlns attibute в конфигурации корневой узел):

ДО: <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">

ПОСЛЕ: <configuration>

0 голосов
/ 17 сентября 2016

Очевидно, есть расширение для Visual Studio 2015

https://visualstudiogallery.msdn.microsoft.com/05bb50e3-c971-4613-9379-acae2cfe6f9e

Этот пакет позволяет вам преобразовать ваш app.config или любой другой файл XML на основе конфигурации сборки

...