1

我正在尝试构建一个 MSBuild 文件以将一组多个网站部署到多个环境。目前,我已经构建了该项目并将其转储到一个目录中。

我使用变量 $(AdminConsoleConfigFilePath) 来引用此目录中 web.config 文件的路径。我的替换文件由变量 $(AdminConsoleConfigReplacementFile) 表示。我在项目的 msbuild 文件中设置了以下任务:

<Target Name="AdminConsoleConfig" DependsOnTargets="BuildAdminConsole">
<Message Text="Beginning configuration for AdminConsole at $(AdminConsoleConfigFilePath) using $(AdminConsoleConfigReplacementFile)" Importance="high"/>
<XmlMassUpdate ContentFile="$(AdminConsoleConfigFilePath)" SubstitutionsFile="$(AdminConsoleConfigurationReplacementPath)" 
               ContentRoot="$(ConfigurationContentReplacementXPathRoot)" SubstitutionsRoot="$(SubstitutionsXPathRoot)"/>
<Message Text="Finished configuration for AdminConsole using $(AdminConsoleConfigReplacementFile)" Importance="high"/>

`

这里其他变量的值声明如下:

<ConfigurationContentReplacementXPathRoot>/configuration</ConfigurationContentReplacementXPathRoot>
<SubstitutionsXPathRoot>/configuration/substitutions/$(Environment)</SubstitutionsXPathRoot>

Environment 是构建目标的名称。在这种情况下,它是“qa”。

我的 web.config 具有典型的 hibernate-config 部分,如下所示:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
        <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
        <property name="connection.isolation">ReadCommitted</property>
        <property name="dialect">NHibernate.Dialect.MsSql2005Dialect</property>
        <property name="connection.driver_class">NHibernate.Driver.SqlClientDriver</property>
  <property name="connection.connection_string">[redacted]</property>
        <property name="show_sql">false</property>
        <property name="generate_statistics">true</property>
        <property name="current_session_context_class">web</property>
        <property name="adonet.batch_size">250</property>
        <property name="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</property>
        <mapping assembly="[redacted]"/>
    </session-factory>
</hibernate-configuration>

我的替换文件如下所示:

<configuration xmlns:xmu="urn:msbuildcommunitytasks-xmlmassupdate">


<substitutions>
<dev></dev>
<qa>
  <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
    <session-factory>
      <property xmu:key="name" xmu:Transform="Replace" xmu:Locator="Match(name)" name="connection.connection_string">[redacted-qa]</property>
    </session-factory>
  </hibernate-configuration>
</qa>

现在,connection.connection_string 属性没有被替换(在上面的代码中,我也永远无法在此站点的编辑器中显示用于配置和替换的结束标记 - 可能是 firefox 问题)。有任何想法吗?我尝试了以下方法:

  1. 从有问题的 web.config 和替换文件(一起和单独)中删除 nhibernate-configuration 的命名空间声明。
  2. 向 nhibernate 声明添加命名空间前缀,并为其添加相关节点和属性的前缀。再次,单独和组合尝试 web.config 和替换文件。
  3. 尝试使用来自 MSBuild contrib 项目的最新夜间构建。这不仅不起作用,而且还破坏了其他东西。
  4. 尝试使用基于 XPath 的 xmu:Locator。还尝试了使用和不使用 xmu:key 值(甚至尝试用 xmu:Key 替换它)。

我完全被难住了。XMLMassUpdate 东西是否有效?我们希望将 web.config 的 qa 和生产版本(或至少各种敏感位)保留在代码主体之外,以防我们得到初级开发人员或承包商,所以当前的方法web.qa.config 和 web.prod.config 在这一点上并不可行。关于如何实现这一点的任何想法(除了为每个环境保留完整 web.config 的副本并在构建后复制之外)?

谢谢,威尔

4

1 回答 1

1

我自己没有尝试过使用 xmlmassupdate 方法进行配置替换。但是还有一种替代方法是使用 XmlFile/UpdateElement 方法在目标中单独指定每个配置更新,例如

    <MSBuild.ExtensionPack.Xml.XmlFile 
        TaskAction="UpdateElement" 
        File="$(AdminConsoleConfigFilePath)" 
        XPath="/hibernate-configuration/session-factory/property[@name='connection.connection_string']" 
        InnerText="Initial Catalog=MyDatabase;Data Source=$(DatabaseServerInstance)" 
    />

然后,您将配置放在目标文件的标题中,例如

<Choose>
    <When Condition="$(Environment)=='DEV'">
        <PropertyGroup>
            <DatabaseServerInstance>DEVSERVER</DatabaseServerInstance>
        </PropertyGroup>
    </When> 
    <When Condition="$(Environment)=='QA'">
        <PropertyGroup>
            <DatabaseServerInstance>QASERVER</DatabaseServerInstance>
        </PropertyGroup>
    </When> 
    <When Condition="$(Environment)=='PROD'">
        <PropertyGroup>
            <DatabaseServerInstance>PRODSERVER</DatabaseServerInstance>
        </PropertyGroup>
    </When> 
</Choose>

您还可以将“选择”块放入单独的文件中,并将其包含在目标文件中。我个人更喜欢这种方法,因为它允许我们集中环境特定属性的列表,然后可以由多个目标文件使用(例如,如果您要部署多个应用程序,在每个环境中使用相同的数据库服务器)。

于 2011-04-02T02:39:05.303 回答