Перетворення веб-конфігурації не працює


88

У програмі .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.

Хтось може припустити, що може бути не так у цій конфігурації?

Відповіді:


156

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

Якщо ви хочете, щоб це було зроблено в рамках app.configоперації збірки, тоді ви можете використовувати плагін SlowCheetah - XML ​​Transforms Visual Studio:

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


1
Щиро дякую, Ви заощадили мені багато часу.
HaBo

3
вау, у мене знадобилося 2 години, щоб знайти цю відповідь. Дякую за публікацію, я б вирвав волосся.
Арахіс

Здається, що у Visual Studio 2015 (Web) перетворення .config тепер є вбудованою функцією, тому вам більше не потрібні SlowCheetah. Але вбудовані перетворення застосовуватимуться лише в тому випадку, якщо ви публікуєте додаток, а не якщо його запускаєте. Ви можете подивитися тут, як я це вирішив.
Метт

1
Не знаю, чому використовувати це, тоді як відповідь @ komsky надає просте та чисте рішення.
Csaba Toth

1
SlowCheetah чудовий, але з власної документації: "Для веб-проектів файли трансформуються, коли ви публікуєте або пакуєте свою програму." Іншими словами, не під час налагодження.
Даг,

31

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

Зверніть увагу, що існує обхідний шлях, описаний у codeproject .

Він описує, як змінити файл .msproj для перезапису поточного web.config трансформованою версією.

Спочатку я опишу це обхідне рішення як варіант 1 , але нещодавно я знайшов інший варіант 2 , який є простішим у використанні (тому ви можете прокрутити вниз до варіанту 2, якщо хочете):


Варіант 1: Я додав інструкції, взяті з оригінальної статті про кодовий проект (див. Посилання вище), тому що знімки екрана там уже пропали, і я не хочу втрачати всю інформацію:

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, а також інструкції щодо продовження збірки див. Там .

Варіант 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.

Ось короткий огляд того, як шлях змінився для різних версій Visual Studio (якщо у вас немає версії Enterprise ви , можливо , буде потрібно замінити Enterpriseна Professionalв дорозі):

        Шлях до Microsoft.Web.XmlTransform.dllверсії VS (для )
2015                   C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web
2017                   C:\Program Files (x86)\Microsoft Visual Studio\2017\
                          Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web
2019                  C:\Program Files (x86)\Microsoft Visual Studio\2019\
                          Enterprise\MSBuild\Microsoft\VisualStudio\v16.0\Web

Скомпілюйте його та помістіть файл .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, перед публікацією переконайтеся, що ви переробили своє рішення з правильною конфігурацією (як правило, Release). Причина полягає в тому, що Web.Config перезаписується під час налагодження, і в іншому випадку ви можете перетворити неправильний файл.


1
Схоже, публікація CodeProject перенесена. Він використовував скріншоти для своїх зразків коду, і тепер, оскільки його блог не працює, вони втрачені в історії.
Ерік Ллойд,

3
Так, на жаль, скріншоти зникли. Але принаймні текст статті все ще є, описуючи підхід. Я додав текстовий опис до своєї відповіді, щоб уникнути його втрати.
Метт

1
Правда, можливо, можна спробувати зв’язатися з автором Джеймсом Коулманом у codeproject, щоб виправити це там. Не впевнений, що він все ще там активний. @ThomasTeilmann
Метт

Я думаю, це може бути схоже на те, що було на втрачених знімках екрана. Здається, щоб досягти того самого основного результату. stackoverflow.com/a/6437192/1003916
user1003916

22

Відповісти на ваше запитання непросто, оскільки це створює проблему - якщо ви хочете перетворити Web.config за допомогою Web.debug.config - де слід зберігати ефект перетворення? У самій Web.config? Це призведе до перезапису вихідного файлу перетворення! Можливо, тому Visual Studio не робить перетворень під час збірок.

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

  1. Створіть свої конфігураційні перетворення для конфігурацій (налагодження, випуск тощо)
  2. Перейменувати Web.configфайл у Web.base.config- трансформації повинні автоматично перейменовуватись відповідно ( Web.base.Debug.config, тощо)
  3. Додайте наступний XML-файл transformWebConfig.proj до папки проекту:
<?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>
  1. Перейдіть до властивостей вашого проекту, оберіть « Побудувати події» та додайте наступний вміст до командного рядка « Події збірки» :
@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 з дійсними перетвореннями для активної конфігурації.


Найчистіша та найкраща відповідь. Деякі питання: 1. Чому перевірка XML говорить, що елемент TransformXml недійсний у елементі Target? (збірка працює до речі). 2. Тепер, коли це генерує справжній Web.Config, я все ще додаю Web.Config до проекту. Тепер, коли я перемикаюся між налагодженням / випуском, web.config зміниться, але я не обов’язково хочу постійно це фіксувати у вихідному репо.
Csaba Toth

1. Не можу сказати, як VS перевіряє цей XML за допомогою схеми, але це попередження є загальним, тому ви можете ігнорувати його. 2. Це залежить від того, яке репо ви використовуєте, але ви можете, наприклад, використовувати файл git.ignore.
komsky

4
Це добре працювало для мене - просто змінив 12-е у файлі build-event і proj на поточну версію. Для події після складання я використовував: '"$(MSBuildBinPath)\msbuild.exe" $(ProjectDir)TransformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath) і оновлюється , v12.0щоб v14.0у файлі .proj.
Джові

1
Для VS 2017 модифікуйте кожен 12.0до14.0
Csaba Toth

1
1) не забудьте включити згенерований web.config у веб-проект, або після публікації він не скопіюється в цільову папку. 2) якщо на сервері збірки бракує цих двох файлів, просто скопіюйте їх на сервер "Microsoft.Web.Publishing.Tasks", "Microsoft.Web.XmlTransform"
phiree

8

для 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>  

Це, мабуть, найкраща відповідь, але ІМО пропускає фокус. Якщо ви перейдете Web.configз Contentна, Noneтоді ви можете використовувати Source="Web.config" Destination="$(TargetPath).config"(або, можливо, для деяких типів проектів, Destination="$(TargetDir)Web.config"). Я також перемістив перетворення в AfterBuild, оскільки його більше не потрібно робити перед копіюванням файлів.
Пітер Тейлор,

Гаразд, насправді це не працює, бо з якихось причин я не можу налаштувати його для запуску bin.
Пітер Тейлор,

4

На ваше негайне запитання було дано відповідь - пояснення полягає в тому, що перетворення застосовується при публікації, а не при побудові.

Однак я думаю, що він не пропонує рішення про те, як досягти того, що ви хочете зробити.

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

Потім створіть трансформації для різних середовищ, які ви хочете опублікувати, - тестування, інтеграція, виробництво - все, що у вас є. Для цього буде достатньо вбудованої функціональності для перетворення файлів web.config під час публікації. Не потрібно SlowCheetah або редагування подій збірки, а також файлів проекту. Якщо у вас є лише веб-проекти.

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


1

Використовуйте Octopus Deploy (версія спільноти безкоштовна) і нехай вона перетворить web.configвас на вас. Кроки:

  1. Налаштуйте Octopus для розгортання веб-програми
  2. Переконайтеся, що у вас Web.Release.configє Build Actionвластивість, встановлена ​​так Contentсамо, як ваш основний web.configфайл.

Це воно! Решта зробить все без особливих налаштувань. Розгортання веб-сайту IIS за замовчуванням робить це нестандартно:введіть тут опис зображення


Номер 2 - це ключ :)
Реза

0

Очевидно, є розширення для Visual Studio 2015

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

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


SlowCheeta - не нова. він був там давно. Їх випуск 1.1 відбувся 8.09.2011
HaBo

@HaBo Дякую за увагу, я видалив newсвіт як речення.
Амір Астане

0

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

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

ПІСЛЯ: <configuration>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.