web-dev-qa-db-ja.com

Web構成変換が機能しない

.NET MVC 3.0アプリケーションでは、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>

デバッグのために、次の構成変換が定義されています。

web.Debug.config

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

そして、アプリケーションをデバッグモードで実行しますが、SMTPポートはweb.configではなくweb.Debug.configから値を取得しています。

この構成で何が間違っている可能性があるのか​​誰でも提案できますか?

80
HaBo

Web.config変換は、公開操作の一部としてのみ適用されます。

app.configビルド操作の一部としてこれを行う場合、SlowCheetah-XML Transforms Visual Studioプラグインを使用できます。

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

143
devdigital

Visual Studio(2010-2017)は、残念ながらnotをデバッグ中に直接サポートします。これは、公開のみを目的としています-拡張SlowCheetahを使用しても(答えをマーク)それは私のために動作しません(web.configではなくapp.configを使用するプロジェクトのみ)。

には回避策があります codeprojectで説明

.msprojファイルを変更して、変換されたバージョンで現在のweb.configを上書きする方法について説明します。

最初にその回避策をオプション1として説明しますが、最近別のオプション2を見つけました。必要に応じてオプション2に直接進みます):


オプション1:元のcodeprojectの記事からの手順を追加しました(上記のリンクを参照)。スクリーンショットは既になくなっているため、情報全体を失いたくありません。

VS.Netは、ローカル環境を開発し、デバッグするだけでは変換を行いません。ただし、必要に応じてこれを実現するために実行できる手順がいくつかあります。

  • 最初に、デフォルトのデバッグとリリースが達成しようとしているものに対して十分ではないと仮定して、VS.Netで必要な構成を作成します。
  • _web.config_を右クリックして、Add Config Transformsを選択します-これにより、定義された構成ごとに依存する変換構成が作成されます。
  • これで、_web.config_の名前を_web.base.config_に変更できます。
  • _web.config_をプロジェクトに追加します。ビルドするたびに上書きされるため、何が含まれていても構いませんが、プロジェクトの一部にしたいので、VS.Netは私たちに与えません- "プロジェクトはデバッグ用に構成されていません"ポップアップ。
  • _.csproj_ Project Fileを編集し、次のTransformXmlタスクをAfterBuildターゲットに追加します。ここで、_web.base.config_を使用して_web.[configuration].config_ファイルを変換し、_web.config_として保存することがわかります。詳細については、 this Microsoft Q&Aを確認してください。ビルドを拡張する方法については、 there を参照してください。

オプション2:

this answerに基づいて、単純なコンソールアプリ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です。
プロフェッショナル版では、パスのEnterpriseProfessionalに置き換える必要があると思います。プレビューバージョンを使用している場合は、さらに_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;_割り当てを追加した理由を知りたい人のために:Mainからintを返すだけではビルドイベントに役立ちませんでした。詳細を参照してください こちら

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

23
Matt

あなたの質問に答えるのは簡単ではありません。なぜなら、それは問題を引き起こします-Web.configをWeb.debug.configで変換したい場合-変換効果をどこに保存すべきでしょうか? Web.config自体で?これにより、変換ソースファイルが上書きされます。おそらく、それがVisual Studioがビルド中に変換を行わない理由です。

以前のマットの答えは有効ですが、実際のアクティブなソリューション構成をデバッグからリリースなどに実際に変更するときに機能する一般的なソリューションを得るためにそれらを混在させることができます。

  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>
  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ファイルが作成されます。

21
komsky

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

しかし、私はそれがあなたがしたいことを達成する方法についての解決策を提供しないと思います。

私はここ数日間、この正確な問題に取り組んでおり、web.configをクリーンに保ち、それぞれの変換ファイルの環境によって異なるすべてのキーを設定する方法を探しています。私の結論は、最も簡単で最も安定したソリューションは、元のweb.configでデバッグ値を使用することであり、Visual Studioでデバッグを実行するときに常に存在するようにすることです。

次に、公開するさまざまな環境(テスト、統合、実稼働)に合わせてトランスフォームを作成します。これには、公開時にweb.configファイルを変換するためのビルトイン機能があれば十分です。 SlowCheetahやビルドイベントやプロジェクトファイルを編集する必要はありません。 Webプロジェクトのみがある場合。

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

4

vS 2017では、答えが見つかりました here これが非常に人気のあるソリューションのように見えるので、なぜ誰も上記を参照していないのか分かりません。とても簡単です。 VS 2017およびすべてのバージョンで機能させるために、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>  
3
Tom McDonald

Octopus Deploy (Communityエディションは無料)を使用して、web.config あなたのために。手順:

  1. WebアプリケーションをデプロイするためにOctopusをセットアップ
  2. Web.Release.configにはBuild ActionプロパティはContentに設定され、メインweb.configファイル。

それでおしまい! Octopusは特別な設定なしで残りを実行します。デフォルトのIIS Webサイトのデプロイは、すぐにこれを行います: enter image description here

1
Matt Kocaj

どうやらVisual Studio 2015の拡張機能があるようです

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

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

最近、.NET Framework 2.0に基づいて提出された古いweb.configで同じ問題が発生しました。解決策は、単にweb.configの名前空間を削除することでした(xmlns attibute in configuration root node):

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

AFTER:<configuration>

0
Rafael Neto