wake-up-neo.com

Web Config Transform funktioniert nicht

In einer .NET MVC 3.0-Anwendung habe ich die folgende Konfiguration in appSettings:

web.config

<appSettings>
<add key="SMTPHost" value="mail.domain.com"/>
    <add key="SMTPUsername" value="[email protected]"/>
    <add key="SMTPPort" value="25"/>
    <add key="SMTPPwd" value="mypassword"/>
    <add key="EmailFrom" value="[email protected]"/>
</appSettings>

Für das Debuggen habe ich folgende Konfigurationstransformation definiert:

web.Debug.config

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

Und ich führe die Anwendung im Debug-Modus aus, aber mein SMTP-Port nimmt immer noch den Wert aus dem web.config, nicht web.Debug.config.

Kann jemand vorschlagen, was an dieser Konfiguration falsch sein könnte?

80
HaBo

Die Web.config-Transformationen werden nur als Teil eines Veröffentlichungsvorgangs angewendet.

Wenn Sie möchten, dass dies als Teil eines app.config build operation, dann können Sie das Plugin SlowCheetah - XML ​​Transforms Visual Studio verwenden:

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

143
devdigital

Visual Studio (2010 - 2017) unterstützt es leider nicht direkt während des Debuggens, es ist nur zum Veröffentlichen gedacht - auch mit der Erweiterung SlowCheetah (markierte Antwort) funktioniert es nicht für mich (nur für Projekte, die app.config anstelle von web.config verwenden).

Hinweis dass es eine Problemumgehung gibt beschrieben unter codeproject .

Es wird beschrieben, wie Sie die .msproj-Datei ändern, um die aktuelle web.config durch die transformierte Version zu überschreiben.

Ich werde diese Problemumgehung zuerst als Option 1 beschreiben, aber ich habe kürzlich eine andere Option 2 herausgefunden, die einfacher zu verwenden ist (Sie können also direkt zu Option 2 scrollen, wenn Sie möchten ):


Option 1: Ich habe die Anweisungen aus dem ursprünglichen Codeprojekt-Artikel hinzugefügt (siehe Link oben), da die Screenshots dort bereits verschwunden sind und ich nicht verlieren möchte die gesamte Information:

VS.Net wandelt sich nicht um, wenn Sie Ihre lokale Umgebung entwickeln und nur debuggen. Aber es gibt einige Schritte, die Sie tun können, um dies zu erreichen, wenn Sie möchten.

  • Erstellen Sie zunächst die gewünschten Konfigurationen in VS.Net , vorausgesetzt, das Standard-Debugging und die Standard-Release reichen nicht für das, was Sie erreichen möchten.
  • Klicken Sie mit der rechten Maustaste auf web.config Und wählen Sie Add Config Transforms (Konfigurationsumwandlungen hinzufügen) -, um eine abhängige Transformationskonfiguration für jede Ihrer definierten Konfigurationen zu erstellen.
  • Jetzt können Sie Ihren web.config In web.base.config Umbenennen.
  • Fügen Sie Ihrem Projekt einen web.config Hinzu. Es spielt keine Rolle, was darin enthalten ist, da es jedes Mal überschrieben wird, wenn wir einen Build ausführen, aber wir möchten, dass es Teil des Projekts ist, sodass VS.Net uns nicht das "Your Project") gibt ist nicht für das Debuggen konfiguriert " Popup.
  • Bearbeiten Sie die Projektdatei.csprojund fügen Sie die folgende Aufgabe TransformXml zum AfterBuild-Ziel hinzu. Hier können Sie sehen, dass ich die web.base.config - Datei mit web.[configuration].config Umwandle und sie als web.config Speichere. Weitere Informationen finden Sie unter this Microsoft Q & A. Anweisungen zum Erweitern des Builds finden Sie unter there .

Option 2:

Basierend auf der Antwort this habe ich eine einfache Konsolenanwendung entwickelt, TransformConfig.exe (in C # 6.0-Syntax):

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

namespace TransformConfig
{

  class Program
  {
    static int Main(string[] args)
    {
        var myDocumentsFolder = [email protected]"C:\Users\{Environment.UserName}\Documents";
        var myVsProjects = [email protected]"{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)
                                    ? [email protected]"{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);
    }

  }
}

Stellen Sie sicher, dass Sie die DLL "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.XmlTransform.dll" als Referenz hinzufügen (dieses Beispiel gilt für VS 2015, für ältere Versionen ersetzen Sie den v14.0 Im Pfad durch die entsprechende Version Nummer, zB v11.0).

Für Visual Studio 2017, hat sich das Namensschema für den Pfad geändert: Beispiel: Für die Enterprise-Version ist es hier: C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\Web.
Ich gehe davon aus, dass Sie für die Professional-Version Enterprise im Pfad durch Professional ersetzen müssen. Wenn Sie die Vorschau-Version verwenden, ersetzen Sie zusätzlich 2017 Durch Preview.

Kompilieren Sie es und speichern Sie die EXE-Datei in einem Verzeichnis, z. C:\MyTools\.

Verwendung: Sie können es in Ihrem Post-Build-Ereignis verwenden (in Projekteigenschaften , wählen Sie Build-Ereignisse und bearbeiten Sie dann das Befehlszeile für Post-Build-Ereignis ). Befehlszeilenparameter sind (Beispiel):

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

zuerst der Name der Konfigurationsdatei, gefolgt von der Transformationskonfigurationsdatei, gefolgt von einer optionalen Schablonenkonfiguration, gefolgt vom Pfad zu Ihrem Projekt, das beide Dateien enthält.

Ich habe den optionalen Parameter template config hinzugefügt, da ansonsten Ihre ursprüngliche vollständige Konfiguration durch die Transformation überschrieben würde. Dies kann durch die Bereitstellung einer Vorlage vermieden werden.

Erstellen Sie die Vorlage, indem Sie einfach die ursprüngliche Datei "Web.config" kopieren und als "Web.Template.config" bezeichnen.

Hinweis:

  • Wenn Sie möchten, können Sie die Datei TransformConfig.exe Auch in den oben genannten Visual Studio-Pfad kopieren, in dem sich der Microsoft.Web.XmlTransform.dll Befindet, und in all Ihren Projekten darauf verweisen, in denen Sie Ihre Konfigurationen transformieren müssen.

  • Für diejenigen unter Ihnen, die sich fragen, warum ich Environment.ExitCode = x; - Zuweisungen hinzugefügt habe: Das einfache Zurückgeben eines Int von Main hat im Build-Ereignis nicht geholfen. Siehe Details hier.

  • Wenn Sie Ihr Projekt veröffentlichen und eine Web.Template.config verwenden, stellen Sie sicher, dass Sie vor der Veröffentlichung eine Neuerstellung für Ihre Projektmappe mit der richtigen Konfiguration (normalerweise Release) durchgeführt haben. Der Grund dafür ist, dass die Web.Config während des Debuggens überschrieben wird und Sie andernfalls möglicherweise die falsche Datei transformieren.

23
Matt

Die Beantwortung Ihrer Frage ist nicht einfach, da dies ein Problem darstellt - wenn Sie Web.config mit Web.debug.config transformieren möchten - wo soll der Transformationseffekt gespeichert werden? In der Web.config selbst? Dies würde die Transformationsquelldatei überschreiben! Wahrscheinlich führt Visual Studio deshalb während der Erstellung keine Transformationen durch.

Die vorherige Antwort von Matt ist gültig, aber Sie können sie mischen, um eine allgemeine Lösung zu erhalten, die funktioniert, wenn Sie die Konfiguration der aktiven Lösung von Debug- auf Release-Konfiguration usw. ändern. Hier ist eine einfache Lösung:

  1. Erstellen Sie Ihre Konfigurationsumwandlungen für Konfigurationen (Debug, Release usw.).
  2. Benennen Sie die Datei Web.config In Web.base.config Um - Transformationen sollten sich automatisch entsprechend umbenennen (Web.base.Debug.config Usw.)
  3. Fügen Sie folgende XML-Datei transformWebConfig.proj zu Ihrem Projektordner hinzu:
<?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. Navigieren Sie zu Ihren Projekteigenschaften, wählen Sie Build Events und fügen Sie folgenden Inhalt zu Postbuild Event Command Line hinzu:
@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)

Wenn Sie jetzt Ihre Lösung erstellen, wird eine Web.config-Datei mit gültigen Transformationen für die aktive Konfiguration erstellt.

21
komsky

Ihre unmittelbare Frage wurde beantwortet. Die Erklärung lautet, dass die Transformation beim Veröffentlichen und nicht beim Erstellen angewendet wird.

Ich denke jedoch, dass es keine Lösung dafür gibt, wie das erreicht werden kann, was Sie tun möchten.

Ich habe seit einigen Tagen mit genau diesem Problem zu kämpfen und nach einer Möglichkeit gesucht, die Datei web.config sauber zu halten und alle Schlüssel festzulegen, die je nach Umgebung in den jeweiligen Transformationsdateien variieren. Mein Fazit ist, dass die einfachste und stabilste Lösung darin besteht, Debug-Werte in der ursprünglichen web.config zu verwenden. Auf diese Weise sind sie immer vorhanden, wenn Sie Debug-Vorgänge in Visual Studio ausführen.

Erstellen Sie dann Transformationen für die verschiedenen Umgebungen, die Sie veröffentlichen möchten - Test, Integration, Produktion - was auch immer Sie haben. Die jetzt integrierte Funktionalität zum Transformieren von web.config-Dateien beim Veröffentlichen ist hierfür ausreichend. Sie müssen weder SlowCheetah noch Build-Ereignisse oder Projektdateien bearbeiten. Wenn Sie nur Webprojekte haben, ist das.

Wenn Sie möchten, können Sie auch die Datei web.debug.config in Ihrer Lösung haben, um eine separate Datei mit allen Werten für die Entwicklungsumgebung zu erstellen. Achten Sie darauf, dass die Werte nicht angewendet werden, wenn Sie in Visual Studio ausgeführt werden, falls jemand anderes versucht, sie zu diesem Zweck zu verwenden!

4

für den VS 2017 habe ich die Antwort gefunden hier nicht sicher, warum niemand darauf verwiesen hat, da dies eine sehr beliebte Lösung zu sein scheint. Sehr einfach auch. Stellen Sie sicher, dass Sie den Kommentar von IOrlandoni am 5. März 2019 sehen, damit er in VS 2017 und allen Versionen funktioniert.

Grundsätzlich ist es ein Zwei-Schritt. Zuerst bearbeiten Sie die .csproj-Datei und fügen den folgenden Code hinzu. Zweitens erstellen Sie eine neue web.base.config-Konfiguration und kopieren dort die vorhandene web.config. Danach überschreibt jeder Build Ihre web.config mit der gewünschten Umwandlung.

    <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>  
3
Tom McDonald

Verwenden Sie Octopus Deploy (Community Edition ist kostenlos) und lassen Sie das web.config für dich. Schritte:

  1. Richten Sie Octopus für die Bereitstellung Ihrer Webanwendung ein
  2. Stellen Sie sicher, dass Ihre Web.Release.config hat die Build Action Eigenschaft auf Content gesetzt, genau wie Ihr Haupt-web.config Datei.

Das ist es! Octopus erledigt den Rest ohne spezielle Konfiguration. Eine standardmäßige IIS Website-Bereitstellung erledigt dies sofort: enter image description here

1
Matt Kocaj

Anscheinend gibt es eine Erweiterung für Visual Studio 2015

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

Mit diesem Paket können Sie Ihre app.config oder eine andere XML-Datei basierend auf der Build-Konfiguration transformieren

Vor kurzem hatte ich das gleiche Problem mit einem älteren web.config, das auf .NET Framework 2.0 basiert. Die Lösung bestand darin, einfach den Namespace der web.config zu entfernen (xmlns attibute in configuration root node):

VOR: <configuration xmlns="http://schemas.Microsoft.com/.NetConfiguration/v2.0">

NACH: <configuration>

0
Rafael Neto