163

デバッグ ビルドとリリース ビルド用に異なる構成ファイルを持つ .NET アプリケーションがあります。たとえば、デバッグ app.config ファイルは、デバッグが有効になっている開発用SQL Serverを指し、リリース ターゲットはライブ SQL Server を指します。他の設定もあり、その一部はデバッグ/リリースで異なります。

現在、2 つの個別の構成ファイル (debug.app.config と release.app.config) を使用しています。プロジェクトにビルド イベントがあり、これがリリース ビルドの場合は release.app.config を app.config にコピーし、そうでない場合は debug.app.config を app.config にコピーします。

問題は、アプリケーションが settings.settings ファイルから設定を取得しているように見えるため、Visual Studio で settings.settings を開く必要があるため、設定が変更されたことを示すプロンプトが表示されるので、変更を受け入れて settings.settings を保存し、正しい設定を使用するように再構築します。

同様の効果を達成するためのより良い/推奨/推奨される方法はありますか? または同様に、私はこれに完全に間違ったアプローチをしましたか?より良いアプローチはありますか?

4

13 に答える 13

62

環境によって異なる構成は、アプリケーション レベルではなく、マシン レベルで保存する必要があります。(構成レベルの詳細。)

これらは、私が通常マシン レベルで保存する構成要素の種類です。

各環境 (開発者、統合、テスト、ステージング、ライブ) がc:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIGディレクトリに固有の設定を持っている場合、アプリケーション コードを環境間でプロモートできます。ビルド後の変更。

そして明らかに、マシン レベルの CONFIG ディレクトリの内容は、アプリとは別のリポジトリまたは別のフォルダー構造でバージョン管理されます。configSourceをインテリジェントに使用することで、.config ファイルをよりソース管理しやすいものにすることができます。

私はこれを 7 年間、25 以上の企業で 200 以上の ASP.NET アプリケーションで行ってきました。(自慢するつもりはありませんが、このアプローチがうまくいかない状況を見たことがないことをお伝えしたいだけです。)

于 2009-01-07T22:09:41.957 に答える
52

これは、Settings.settingsとApp.configを扱う一部の人に役立つ場合があります。VisualStudio(私の場合はVisual Studio 2008)のSettings.settingsグリッドの値を編集するときに、[プロパティ]ペインのGenerateDefaultValueInCode属性に注意してください。

GenerateDefaultValueInCodeをTrueに設定すると(ここではTrueがデフォルトです!)、デフォルト値はEXE(またはDLL)にコンパイルされ、プレーンテキストエディターで開くとファイルに埋め込まれていることがわかります。

私はコンソールアプリケーションで作業していましたが、EXEをデフォルトにした場合、アプリケーションは常に同じディレクトリに配置された構成ファイルを無視していました。かなりの悪夢であり、インターネット全体でこれに関する情報はありません。

于 2009-08-26T08:44:02.030 に答える
34

ここに関連する質問があります:

ビルド プロセスの改善

構成ファイルには、設定を上書きする方法が付属しています。

<appSettings file="Local.config">

2 つ (またはそれ以上) のファイルをチェックインする代わりに、既定の構成ファイルのみをチェックインしてから、各ターゲット コンピューターに Local.config を配置し、その特定のコンピューターのオーバーライドを含む appSettings セクションだけを配置します。

構成セクションを使用している場合、同等のものは次のとおりです。

configSource="Local.config"

もちろん、他のマシンからすべての Local.config ファイルのバックアップ コピーを作成し、それらをどこかにチェックインすることは良い考えですが、実際のソリューションの一部としてではありません。各開発者は、Local.config ファイルに「無視」を設定して、チェックインされないようにします。これにより、他のすべてのファイルが上書きされます。

(実際に「Local.config」と呼ぶ必要はありません。それは私が使用しているものです)

于 2008-09-25T10:57:29.060 に答える
14

私が読んでいることから、ビルドプロセスにVisualStudioを使用しているようです。代わりにMSBuildとNantを使用することを考えましたか?

Nantのxml構文は少し奇妙ですが、一度理解すれば、あなたが言及したことを行うのはかなり簡単になります。

<target name="build">
    <property name="config.type" value="Release" />

    <msbuild project="${filename}" target="Build" verbose="true" failonerror="true">
        <property name="Configuration" value="${config.type}" />
    </msbuild>

    <if test="${config.type == 'Debug'}">
        <copy file=${debug.app.config}" tofile="${app.config}" />
    </if>

    <if test="${config.type == 'Release'}">
        <copy file=${release.app.config}" tofile="${app.config}" />
    </if>

</target>
于 2008-09-25T11:12:24.890 に答える
11

私には、 Visual Studio 2005 Web Deployment Projectの恩恵を受けることができるようです。

これにより、ビルド構成に応じて web.config ファイルのセクションを更新/変更するように指示できます。

簡単な概要/サンプルについては、Scott Gu のこのブログ エントリをご覧ください。

于 2008-09-25T10:57:02.540 に答える
8

以前は Web 配置プロジェクトを使用していましたが、その後 NAnt に移行しました。さまざまな設定ファイルを分岐してコピーする代わりに、現在、構成値をビルド スクリプトに直接埋め込み、xmlpoke タスクを介して構成ファイルに挿入しています。

  <xmlpoke
    file="${stagingTarget}/web.config"
    xpath="/configuration/system.web/compilation/@debug"
    value="true"
  />

どちらの場合でも、構成ファイルには必要な開発者の値を含めることができ、運用システムを壊すことなく、開発環境内から正常に機能します。開発者がテストの際にビルド スクリプトの変数を恣意的に変更する可能性は低いことがわかりました。そのため、偶発的な構成ミスは、私たちが試した他の手法よりもまれでした。ただし、プロセスの早い段階で各変数を追加して、デフォルトでは、dev 値は prod にプッシュされません。

于 2008-09-25T11:36:25.130 に答える
7

私の現在の雇用主は、最初に開発レベル (デバッグ、ステージ、ライブなど) を machine.config ファイルに入れることで、この問題を解決しました。次に、それを取得して適切な構成ファイルを使用するコードを作成しました。これにより、アプリがデプロイされた後に間違った接続文字列の問題が解決されました。

彼らは最近、machine.config 値の値から正しい接続文字列を返す中央 Web サービスを作成しました。

これが最善の解決策ですか?おそらくそうではありませんが、彼らにとってはうまくいきます。

于 2008-09-25T10:46:20.460 に答える
5

私がうまく機能したソリューションの1つは、WebDeploymentProjectを使用することでした。私のサイトには2/3の異なるweb.configファイルがあり、公開時に、選択した構成モード(release / staging / etc ...)に応じて、Web.Release.configをコピーし、名前をwebに変更しました。 AfterBuildイベントで構成し、不要なもの(Web.Staging.configなど)を削除します。

<Target Name="AfterBuild">
    <!--Web.config -->
    <Copy Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " SourceFiles="$(SourceWebPhysicalPath)\Web.Release.config" DestinationFiles="$(OutputPath)\Web.config" />
    <Copy Condition=" '$(Configuration)|$(Platform)' == 'Staging|AnyCPU' " SourceFiles="$(SourceWebPhysicalPath)\Web.Staging.config" DestinationFiles="$(OutputPath)\Web.config" />
    <!--Delete extra files -->
    <Delete Files="$(OutputPath)\Web.Release.config" />
    <Delete Files="$(OutputPath)\Web.Staging.config" />
    <Delete Files="@(ProjFiles)" />
  </Target>
于 2008-09-25T11:14:20.113 に答える
3

ここで別の解決策を見つけることができます: ASP.NET で開発/UAT/Prod 環境間で構成を切り替える最良の方法は? XSLT を使用して web.config を変換します。

NAnt の使用に関するいくつかの良い例もあります。

于 2008-09-25T12:28:17.563 に答える
3

私たちのプロジェクトには、dev、qa、uat、prod の構成を維持しなければならないという同じ問題があります。これが私たちが従ったものです(MSBuildに精通している場合にのみ適用されます):

MSBuild コミュニティ タスク拡張機能と共に MSBuild を使用します。これには、開始する正しいノードを指定すると、任意の XML ファイルのエントリを「一括更新」できる「XmlMassUpdate」タスクが含まれます。

実装する:

1) dev 環境エントリを持つ構成ファイルが 1 つ必要です。これは、ソリューションの構成ファイルです。

2)環境ごとに異なるエントリ(主にappSettingsとConnectionStrings)のみを含む「Substitutions.xml」ファイルが必要です。環境全体で変更されないエントリは、このファイルに入れる必要はありません。それらはソリューションの web.config ファイルに存在することができ、タスクによって影響を受けることはありません

3) ビルド ファイルで、XML 一括更新タスクを呼び出し、適切な環境をパラメーターとして指定するだけです。

以下の例を参照してください。

    <!-- Actual Config File -->
    <appSettings>
        <add key="ApplicationName" value="NameInDev"/>
        <add key="ThisDoesNotChange" value="Do not put in substitution file" />
    </appSettings>

    <!-- Substitutions.xml -->
    <configuration xmlns:xmu="urn:msbuildcommunitytasks-xmlmassupdate">
      <substitutions>
        <QA>
           <appSettings>
            <add xmu:key="key" key="ApplicationName" value="NameInQA"/>
           </appSettings>            
        </QA>
        <Prod>
          <appSettings>
            <add xmu:key="key" key="ApplicationName" value="NameInProd"/>
          </appSettings>            
        </Prod>
     </substitutions>
    </configuration>


<!-- Build.xml file-->

    <Target Name="UpdateConfigSections">
            <XmlMassUpdate ContentFile="Path\of\copy\of\latest web.config" SubstitutionsFile="path\of\substitutionFile" ContentRoot="/configuration" SubstitutionsRoot="/configuration/substitutions/$(Environment)" />
        </Target>

'$Environment' を、環境に基づいて 'QA' または 'Prod' に置き換えます。あなたはのために構築しています。回復不可能なミスを避けるために、実際の構成ファイル自体ではなく、構成ファイルのコピーで作業する必要があることに注意してください。

ビルド ファイルを実行し、更新された構成ファイルを展開環境に移動するだけで完了です。

より良い概要については、これを読んでください:

http://blogs.microsoft.co.il/blogs/dorony/archive/2008/01/18/easy-configuration-deployment-with-msbuild-and-the-xmlmassupdate-task.aspx

于 2009-06-18T21:42:15.683 に答える
2

あなたのように、「マルチ」app.configもセットアップしました-たとえば、app.configDEV、app.configTEST、app.config.LOCAL。いくつかの優れた代替案が提案されていますが、それが機能する方法が気に入った場合は、次を追加します。


<appSettings>
<add key = "Env" value = "[Local] "/> アプリごとに、タイトルバーの UI にこれを追加します。 from ConfigurationManager.AppSettings.Get("Env") ;

構成の名前をターゲットのものに変更するだけです(4つのイベントに対して多くのデータベース/ wcf構成を持つ8つのアプリを含むプロジェクトがあります)。それぞれにクリックオンスでデプロイするには、プロジェクト内の 4 つの設定を変更して実行します。(これは自動化したい)

私の唯一の落とし穴は、手動で名前を変更した後、古い構成が「スタック」しているため、変更後に「すべてをクリーンアップ」することを忘れないことです。(これでsetting.settingの問題が解決すると思います)。

これは非常にうまく機能することがわかりました (いつか、MSBuild/NAnt を調べる時間ができるでしょう)。

于 2009-02-26T12:32:22.540 に答える
0

上記のasp.netには、設定をデータベースに保存し、カスタムキャッシュを使用して取得してみませんか?

これを行った理由は、本番ファイルを継続的に更新する許可を取得するよりも、データベースを継続的に更新する方が(私たちにとって)簡単だからです。

カスタムキャッシュの例:

public enum ConfigurationSection
{
    AppSettings
}

public static class Utility
{
    #region "Common.Configuration.Configurations"

    private static Cache cache = System.Web.HttpRuntime.Cache;

    public static String GetAppSetting(String key)
    {
        return GetConfigurationValue(ConfigurationSection.AppSettings, key);
    }

    public static String GetConfigurationValue(ConfigurationSection section, String key)
    {
        Configurations config = null;

        if (!cache.TryGetItemFromCache<Configurations>(out config))
        {
            config = new Configurations();
            config.List(SNCLavalin.US.Common.Enumerations.ConfigurationSection.AppSettings);
            cache.AddToCache<Configurations>(config, DateTime.Now.AddMinutes(15));
        }

        var result = (from record in config
                      where record.Key == key
                      select record).FirstOrDefault();

        return (result == null) ? null : result.Value;
    }

    #endregion
}

namespace Common.Configuration
{
    public class Configurations : List<Configuration>
    {
        #region CONSTRUCTORS

        public Configurations() : base()
        {
            initialize();
        }
        public Configurations(int capacity) : base(capacity)
        {
            initialize();
        }
        public Configurations(IEnumerable<Configuration> collection) : base(collection)
        {
            initialize();
        }

        #endregion

        #region PROPERTIES & FIELDS

        private Crud _crud; // Db-Access layer

        #endregion

        #region EVENTS
        #endregion

        #region METHODS

        private void initialize()
        {
            _crud = new Crud(Utility.ConnectionName);
        }

        /// <summary>
        /// Lists one-to-many records.
        /// </summary>
        public Configurations List(ConfigurationSection section)
        {
            using (DbCommand dbCommand = _crud.Db.GetStoredProcCommand("spa_LIST_MyConfiguration"))
            {
                _crud.Db.AddInParameter(dbCommand, "@Section", DbType.String, section.ToString());

                _crud.List(dbCommand, PopulateFrom);
            }

            return this;
        }

        public void PopulateFrom(DataTable table)
        {
            this.Clear();

            foreach (DataRow row in table.Rows)
            {
                Configuration instance = new Configuration();
                instance.PopulateFrom(row);
                this.Add(instance);
            }
        }

        #endregion
    }

    public class Configuration
    {
        #region CONSTRUCTORS

        public Configuration()
        {
            initialize();
        }

        #endregion

        #region PROPERTIES & FIELDS

        private Crud _crud;

        public string Section { get; set; }
        public string Key { get; set; }
        public string Value { get; set; }

        #endregion

        #region EVENTS
        #endregion

        #region METHODS

        private void initialize()
        {
            _crud = new Crud(Utility.ConnectionName);
            Clear();
        }

        public void Clear()
        {
            this.Section = "";
            this.Key = "";
            this.Value = "";
        }
        public void PopulateFrom(DataRow row)
        {
            Clear();

            this.Section = row["Section"].ToString();
            this.Key = row["Key"].ToString();
            this.Value = row["Value"].ToString();
        }

        #endregion
    }
}
于 2011-05-24T17:38:22.727 に答える
0

Web.config:

IIS でアプリケーションをホストする場合は、Web.config が必要です。Web.config は、IIS が Kestrel の前でリバース プロキシとしてどのように動作するかを構成するための必須の構成ファイルです。IIS でホストする場合は、web.config を維持する必要があります。

AppSetting.json:

IIS に関係のないその他すべてのことについては、AppSetting.json を使用します。AppSetting.json は、Asp.Net Core ホスティングに使用されます。ASP.NET Core は、"ASPNETCORE_ENVIRONMENT" 環境変数を使用して現在の環境を判断します。デフォルトでは、この値を設定せずにアプリケーションを実行すると、自動的に本番環境にデフォルト設定され、「AppSetting.production.json」ファイルが使用されます。Visual Studio 経由でデバッグすると、環境が Development に設定されるため、「AppSetting.json」が使用されます。Windows でホスティング環境変数を設定する方法については、この Web サイトを参照してください。

App.config:

App.config は、主に Windows フォーム、Windows サービス、コンソール アプリ、および WPF アプリケーションで使用される .NET で使用される別の構成ファイルです。コンソール アプリケーション経由で Asp.Net Core ホスティングを開始すると、app.config も使用されます。


TL;DR

構成ファイルの選択は、サービス用に選択したホスティング環境によって決まります。IIS を使用してサービスをホストしている場合は、Web.config ファイルを使用します。他のホスティング環境を使用している場合は、App.config ファイルを使用します。構成ファイルを使用したサービスの構成に関するドキュメントを参照し、ASP.NET Core での構成 も確認してください。

于 2018-09-10T07:12:46.600 に答える