我们开发一个系统,其中客户端应用程序是使用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>
但很明显,这不是问题的最佳解决方案,随着配置选择数量的增加,它变得有点难以管理。任何建议如何改善这一点是最受欢迎的。
问候,奥拉
答案 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>