在app.config中管理多个客户端端点配置(IP地址等)的最佳方法

时间:2012-06-07 12:00:45

标签: .net web-services

我们开发一个系统,其中客户端应用程序是使用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>

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

问候,奥拉

3 个答案:

答案 0 :(得分: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文件

此解决方案确实运行良好,可以回过头来解决任何问题

答案 1 :(得分:1)

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

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

如果您要详细说明部署策略,以便为您的情况提供一些具体的答案,那将会很有帮助。

编辑:我应该添加这仅适用于内部产品,如果您在外部提供MSI,则不希望使用此方法。

答案 2 :(得分:1)

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

我们目前使用的解决方案是此帖子中建议的条件编译:

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

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

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

    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>