在运行时更改WSDL EndPointAddress的地址/端口?

时间:2010-04-19 20:20:44

标签: wcf web-services wsdl app-config

所以我目前在我的解决方案中添加了2个WSDL作为服务引用。它们在我的app.config文件中看起来像这样(我删除了“bindings”字段,因为它不感兴趣):

<system.serviceModel>
  <client>
    <endpoint address="http://localhost:8080/query-service/jse" binding="basicHttpBinding" bindingConfiguration="QueryBinding" contract="QueryService.Query" name="QueryPort" />
    <endpoint address="http://localhost:8080/dataimport-service/jse" binding="basicHttpBinding" bindingConfiguration="DataImportBinding" contract="DataService.DataImport" name="DataImportPort" />
  </client>   
</system.serviceModel>

当我使用WSDL时,它看起来像这样:

using (DataService.DataClient dClient = new DataService.DataClient())
{
  DataService.importTask impt = new DataService.importTask();
  impt.String_1 = "someData";
  DataService.importResponse imptr = dClient.importTask(impt);
}

在“using”语句中,当实例化DataClient对象时,我有5个构造函数可供我使用。在这种情况下,我使用默认构造函数:

   new DataService.DataClient()

使用内置的端点地址字符串,我假设它是从app.config中提取的。但我希望应用程序的用户可以选择更改此值。

1)以编程方式获取此字符串的最佳/最简单方法是什么?

2)然后,一旦我允许用户编辑和测试值,我应该在哪里存储它?

我希望将它存储在一个地方(比如app.config或等效的),这样就不需要检查值是否存在以及我是否应该使用备用构造函数。 (为了保持我的密码,你知道吗?)

有什么想法吗?建议?

修改

也许我应该问一下这些替代构造函数。

例如,其中一个看起来像这样:

   new DataService.DataClient(string endPointConfigurationName, 
                              string remoteAddress)

“endPointConfigurationName”和“remoteAddress”可以传递什么值?

EDIT2

在这里回答我自己的问题,“endPointConfigurationName”看起来与app.config XML中的“name”相同,“remoteAddress”的格式与app.config XML中的“endpoint address”相同。

另外!关于获取EndPointAddresses的第一个问题的答案如下:

ClientSection clSection =
   ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection;

ChannelEndpointElementCollection endpointCollection =
   clSection.ElementInformation.Properties[string.Empty].Value as ChannelEndpointElementCollection;

Dictionary<string, string> nameAddressDictionary = 
   new Dictionary<string, string>();

foreach (ChannelEndpointElement endpointElement in endpointCollection)
{
   nameAddressDictionary.Add(endpointElement.Name, 
                             endpointElement.Address.ToString());
}

EDIT3

好的,我想我已经找到了问题的下半部分(因此,完全解决方案)。我在另一个网站上发现了这个,我修改它以满足我的需求:

Configuration configuration; 
ServiceModelSectionGroup serviceModelSectionGroup;
ClientSection clientSection;

configuration = 
    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
serviceModelSectionGroup = 
    ServiceModelSectionGroup.GetSectionGroup(configuration);
clientSection = serviceModelSectionGroup.Client;

foreach (ChannelEndpointElement endPt in clientSection.Endpoints)
{
  MessageBox.Show(endPt.Name + " = " + endPt.Address);
}
configuration.Save();

使用此代码,我们可以访问clientSection.Endpoints,并可以访问和更改所有成员属性,例如“Address”。然后当我们完成更改它们时,我们可以执行configuration.Save()并将所有值写入用户文件。

现在是抓住了。在调试模式下,“configuration.save()”似乎实际上没有将值从执行执行到执行,但是当运行应用程序正常(在调试模式之外)时,值仍然存在。 (这很好。)这是唯一的警告。

EDIT4

还有另一个警告。对WSDL所做的更改在运行时不会生效。需要重新启动应用程序才能将用户配置文件值重新读入内存(显然。)


我可能感兴趣的唯一另一件事是找到一种方法(一旦值被更改)将值恢复为默认值。当然,您可以删除用户文件,但删除所有自定义设置。

有什么想法吗?

EDIT5

我认为依赖注入在这里可能是完美的,但需要进一步研究......

编辑6

我没有评论权限,但您需要运行

ConfigurationManager.RefreshSection("client");

更新缓存,以便立即进行更改。

1 个答案:

答案 0 :(得分:2)

如果您使用Microsoft 添加Web引用来创建服务引用,那么我认为您可能无法以编程方式更改连接。即使您确实更改了自动生成的代码,只要您执行了更新服务参考,它就会被覆盖。

最好的办法是抓住微软自动生成的代码并构建自己的WCF类。这并不困难,并提供了很多灵活性/可扩展性。

Here's an excellent article关于这个主题。

至于存储自定义地址,它取决于您的应用程序,无论是Silverlight,Windows还是Web应用程序。我个人的选择是数据库。