5

我们开发了一个系统,其中客户端应用程序是一个使用 Web 服务与服务器通信的 .NET 客户端。我们需要能够使用不同的配置选项来部署客户端,例如 IP 地址等。到目前为止,我们已经通过在 app.config 中基本上注释/取消注释不同的配置来管理这个问题,例如:

<!--<client>
    <endpoint address="https://localhost/services/service1"
        binding="customBinding" bindingConfiguration="ServiceSoapBinding"
        contract="ServiceReference.Service1" name="ServiceImplPort" />
    <endpoint address="https://localhost/services/service2"
        binding="customBinding" bindingConfiguration="ServiceSoapBinding"
        contract="ServiceReference.Service2" name="ServiceImplPort" />
    ...
    ..
</client>-->
<client>
    <endpoint address="https://prod.example.com/services/service1"
        binding="customBinding" bindingConfiguration="ServiceSoapBinding"
        contract="ServiceReference.Service1" name="ServiceImplPort" />
    <endpoint address="https://prod.example.com/services/service2"
        binding="customBinding" bindingConfiguration="ServiceSoapBinding"
        contract="ServiceReference.Service2" name="ServiceImplPort" />
    ...
    ..
</client>

但很明显,这不是解决问题的最佳方案,随着配置替代方案数量的增加,它变得有点难以管理。任何如何改进这一点的建议都非常受欢迎。

问候, 奥拉

4

3 回答 3

2

幸运的是,这个问题有一个很好的解决方案。下载并安装MSBuild.Community.Tasks

然后查看以下帖子以了解示例用法

http://chris.widdowson.id.au/?p=781

http://grahamrhay.wordpress.com/2012/03/16/multiple-config-transforms-at-build-time/

警告 设置时间超过 5 分钟,您将手动编辑 .csproj 文件

这个解决方案效果很好,有任何问题请回来

于 2012-06-07T14:36:10.723 回答
1

我们很高兴使用 MSI 包来部署我们的应用程序(使用 WiX 构建)以及调用与我们的产品一起打包的 XMLPreprocess 可执行文件的自定义操作。它基本上使用 XPath 和我们使用 Excel 维护的一些 XML 文件来处理重新配置 app/web.config 文件。我们已经使用它很长一段时间了,并且对产品没有任何问题。

这是一个链接:http: //xmlpreprocess.codeplex.com/

如果您要详细说明您的部署策略以针对您的情况给出一些具体的答案,这将很有帮助。

编辑:我可能应该补充一下,这仅适用于内部产品,如果您在外部提供 MSI,您不会想使用这种方法。

于 2012-06-07T16:52:23.043 回答
1

我们确实尝试了 wal 的方法,该方法几乎解决了问题,但我们遇到了单击一次部署的问题,请参阅我对 wal 答案的评论。

我们目前使用的解决方案是本文建议的条件编译:

http://www.codeproject.com/Articles/451734/Visual-Studio-Use-Conditional-Compilation-to-Contr

优点是,除了单击一次可以完美地工作之外,您不必调整 VS 项目文件或使用任何第三方组件。缺点是如果要添加/更改端点,则需要更新源代码。

我们所做的是在项目中添加一个新的.settings文件。这不是强制性的,但我们认为将端点配置保存在单独的设置文件中是个好主意,因为必须稍微调整该文件。根据为编译启用的配置,它被调整为使用条件编译来启用正确的端点:

    public ServiceSettings() {
        // // To add event handlers for saving and changing settings, uncomment the lines below:
        //
        // this.SettingChanging += this.SettingChangingEventHandler;
        //
        // this.SettingsSaving += this.SettingsSavingEventHandler;
        //

        // Each method corrsponds to a build version. We call all four methods, because
        // the conditional compilation will only compile the one indicated:
        this.SetLocalApplicationSettings();
        this.SetAS12ApplicationSettings();
    }

    [Conditional("LOCAL")]
    private void SetLocalApplicationSettings()
    {
        this["LoginAddress"] = "https://localhost/services/loginservice";
        this["SettingsAddress"] = "https://localhost/services/settingsservice";
    }

    [Conditional("EXAMPLE")]
    private void SetAS12ApplicationSettings()
    {
        this["LoginAddress"] = "https://example.com/services/loginservice";
        this["SettingsAddress"] = "https://example.com/services/settingsservice";
    }

在 VS 中,我们为每个端点创建了一个配置,并在 Build 选项卡上定义了适当的条件编译符号,即 LOCAL 或EXAMPLE。

我们还使用 VS 生成的 WS 客户端类更新了代码,以使用设置文件中定义的端点:

var client = new SettingsServiceClient("SettingsServiceImplPort",
    ServiceSettings.Default.SettingsAddress);

在 app.config 中,我们只保留了默认配置(localhost)和绑定配置以使 VS 满意:

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="SettingsServiceImplServiceSoapBinding">
        <textMessageEncoding messageVersion="Soap12" />
        <httpsTransport />
      </binding>
      <binding name="LoginServiceImplServiceSoapBinding">
        <textMessageEncoding messageVersion="Soap12" />
        <httpsTransport />
      </binding>
    </customBinding>
  </bindings>
  <client>
    <endpoint address="https://localhost/services/settingsservice"
      binding="customBinding" bindingConfiguration="SettingsServiceImplServiceSoapBinding"
      contract="SettingsServiceReference.SettingsService" name="SettingsServiceImplPort" />
    <endpoint address="https://localhost/services/loginservice"
      binding="customBinding" bindingConfiguration="LoginServiceImplServiceSoapBinding"
      contract="LoginServiceReference.LoginService" name="LoginServiceImplPort" />
  </client>
</system.serviceModel>
<applicationSettings>
    <ConfigurationTest.ServiceSettings>
        <setting name="SettingsAddress" serializeAs="String">
            <value>https://localhost/services/settingsservice</value>
        </setting>
        <setting name="LoginAddress" serializeAs="String">
            <value>https://localhost/services/loginservice</value>
        </setting>
    </ConfigurationTest.ServiceSettings>
</applicationSettings>
于 2012-12-11T10:49:56.427 回答