Web構成変換が機能しない


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 VisualStudioプラグインを使用できます。

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


1
本当にありがとうございました。たくさんの時間を節約してくれました。
HaBo 2012年

3
うわー、この答えを見つけるのに2時間かかりました。投稿してくれてありがとう、髪を抜いていただろう。
ピーナッツ2012

Visual Studio 2015 (Web).configでは、変換が組み込み機能になっているため、SlowCheetahは不要になっているようです。ただし、組み込みの変換は、アプリケーションを公開した場合にのみ適用され、実行した場合には適用されません。私がどのようにそれを解決しかをここで見ることができます。
マット

1
@komskyの回答がシンプルでクリーンなソリューションを提供しているのに、なぜこれを使用するのかわからない。
csaba Toth 2017年

1
SlowCheetahは素晴らしいですが、独自のドキュメントから:「Webプロジェクトの場合、アプリケーションを公開またはパッケージ化するとファイルが変換されます。」つまり、デバッグ中ではありません。
ダグ

31

Visual Studio( 2010-2019 は、残念ながら、デバッグ中直接サポートしていません。公開のみを目的としています。拡張子が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。詳細については、確認してください。このマイクロソフト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

ここでは(あなたが交換する必要があるかもしれませんEnterpriseバージョンがない場合は、パスは、Visual Studioの異なるバージョンのためにどのように変化したかを概観だEnterpriseことにより、Professionalパスには):

VSバージョン        パス(のMicrosoft.Web.XmlTransform.dll
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;割り当てを追加したのか疑問に思っている人のために:Mainからintを返すだけでは、ビルドイベントには役立ちませんでした。詳細はこちらをご覧ください。

  • プロジェクトを公開していて、Web.Template.configを使用している場合は、公開する前に、適切な構成(通常はリリース)を使用してソリューションを再構築したことを確認してください。その理由は、デバッグ中にWeb.Configが上書きされ、そうしないと間違ったファイルを変換してしまう可能性があるためです。


1
CodeProjectの投稿がうんざりしているようです。彼はコードサンプルにスクリーンショットを使用しましたが、ブログがダウンしたため、それらは歴史に失われています。
エリックロイド

3
はい、残念ながらスクリーンショットは消えてしまいました。しかし、少なくとも記事のテキストはまだそこにあり、アプローチを説明しています。私はそれを失うことを避けるために私の答えにテキストの説明を追加しました。
マット

1
確かに、codeprojectで作者のJames Colemanに連絡して、そこで修正することができるかもしれません。しかし、彼がまだそこで活動しているかどうかはわかりません。@ThomasTeilmann
マット

これは、失われたスクリーンショットにあったものと似ているかもしれないと思います。同じ基本的な結果を達成するようです。 stackoverflow.com/a/6437192/1003916
user1003916 2016年

22

Web.configをWeb.debug.configで変換する場合、変換効果をどこに保存するかという問題が発生するため、質問への回答は簡単ではありません。Web.config自体で?これにより、変換ソースファイルが上書きされます。おそらくそれが、VisualStudioがビルド中に変換を行わない理由です。

以前のマットの回答は有効ですが、アクティブなソリューション構成をデバッグからリリースなどに実際に変更するときに機能する汎用ソリューションを作成するために、それらを混合することをお勧めします。簡単なソリューションは次のとおりです。

  1. 構成(デバッグ、リリースなど)の構成変換を作成します
  2. Web.configファイルの名前を次のように変更しますWeb.base.config-変換はそれに応じて自動的に名前を変更する必要があります(Web.base.Debug.configなど)
  3. 次のtransformWebConfig.projXMLファイルをプロジェクトフォルダーに追加します。
<?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 2017年

1. VSがスキーマを使用してこのXMLを検証する方法を実際に知ることはできませんが、この警告は一般的であるため、無視してかまいません。2.使用しているリポジトリによって異なりますが、たとえばgit.ignoreファイルエントリを使用できます。
komsky 2017

4
これは私にとってはうまくいきました-build-eventとprojファイルの12を現在のバージョンに変更しただけです。ビルド後のイベントでは、次のものを使用しました。.projファイルでに'"$(MSBuildBinPath)\msbuild.exe" $(ProjectDir)TransformWebConfig.proj /t:TransformWebConfig /p:CurrentConfig=$(ConfigurationName) /p:TargetProjectName=$(TargetPath) 更新v12.0v14.0ました。
Jovie 2017

1
VS 2017の場合、すべて12.0を次のように変更します14.0
Csaba Toth

1
1)生成されたweb.configをWebプロジェクトに含めることを忘れないでください。そうしないと、公開後にターゲットフォルダーにコピーされません。2)ビルドサーバーにこれら2つのファイルがない場合は、サーバー「Microsoft.Web.Publishing.Tasks」、「Microsoft.Web.XmlTransform」にコピーするだけです
phiree 2017年

8

VS 2017のために私は答えを見つけることが、ここで誰もが、非常に人気のあるソリューションであることが表示される上に、それを参照していない理由はないように注意してください。とても簡単です。VS2017およびすべてのバージョンで機能させるための2019年3月5日のIOrlandoniからのコメントを確認してください。

基本的には2ステッパーです。まず、.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>  

これはおそらく最良の答えですが、IMOにはトリックがありません。Web.configからContentに変更するとNone、を使用できますSource="Web.config" Destination="$(TargetPath).config"(または、一部のタイプのプロジェクトではDestination="$(TargetDir)Web.config")。また、AfterBuildファイルをコピーする前に変換を行う必要がなくなったため、変換をに移動しました。
ピーターテイラー

なんらかの理由でから実行するように構成できないため、実際には機能しませんbin
ピーターテイラー

4

あなたの当面の質問に答えました-説明は、変換がビルドではなく公開に適用されるということです。

しかし、それはあなたがやりたいことをどのように達成するかについての解決策を提供しないと思います。

私はこの正確な問題に数日間苦労しており、web.configをクリーンに保ち、それぞれの変換ファイルの環境に応じて異なるすべてのキーを設定する方法を探しています。私の結論は、最も簡単で安定した解決策は、元のweb.configでデバッグ値を使用することです。そうすれば、VisualStudioでデバッグを実行するときに常に存在します。

次に、公開するさまざまな環境(テスト、統合、本番)の変換を作成します。これには、公開時にweb.configファイルを変換するための組み込み機能で十分です。SlowCheetahや、ビルドイベントやプロジェクトファイルの編集は必要ありません。Webプロジェクトしかない場合はそうです。

必要に応じて、ソリューションにweb.debug.configファイルを含めて、開発環境に関連するすべての値を含む別のファイルを保持することもできます。ただし、他の誰かがその目的で使用しようとした場合に備えて、VisualStudioで実行する場合は値が適用されないことを必ずコメントしてください。


1

Octopus Deploy(Communityエディションは無料)を使用してweb.config、あなたに代わって変換してください。手順:

  1. OctopusをセットアップしてWebアプリケーションをデプロイします
  2. プロパティがメインファイルと同じように設定されWeb.Release.configていることを確認してください。Build ActionContentweb.config

それでおしまい!Octopusは、特別な設定なしで残りを実行します。デフォルトのIISWebサイトの展開では、これをすぐに実行できます。ここに画像の説明を入力してください


番号2が鍵です:)
Reza

0

どうやらVisualStudio2015の拡張機能があります

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

このパッケージを使用すると、ビルド構成に基づいてapp.configまたはその他のXMLファイルを変換できます。


SlowCheetaは新しいものではありません。それは長い間そこにありました。彼らの1.1リリースは
2011

@HaBoご清聴ありがとうございましたnew、文として世界を削除しました。
Amir Astaneh 2016

0

最近、.NET Framework2.0に基づく古いweb.configファイルで同じ問題が発生しました。解決策は、web.configの名前空間(構成ルートノードのxmlns属性)を削除することでした。

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

後: <configuration>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.