如何以编程方式修改WCF app.config端点地址设置?
我想以编程方式修改我的app.config文件来设置应该使用哪个服务文件端点。 在运行时执行此操作的最佳方法是什么? 以供参考:
<endpoint address="http://mydomain/MyService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IASRService" contract="ASRService.IASRService" name="WSHttpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint>
我想你想要的是在运行时换出一个你的configuration文件的版本,如果是这样的话,创build一个你的configuration文件的副本(也给它相关的扩展名如.Debug或.Release)具有正确的地址(这给你一个debugging版本和一个运行时版本),并根据构buildtypes创build一个后期构build步骤,以复制正确的文件。
这里是我以前用过的一个postbuild事件的例子,它用正确的版本(debugging/运行时)覆盖了输出文件,
copy "$(ProjectDir)ServiceReferences.ClientConfig.$(ConfigurationName)" "$(ProjectDir)ServiceReferences.ClientConfig" /Y
其中:$(ProjectDir)是configuration文件所在的项目目录$(ConfigurationName)是活动configuration构buildtypes
编辑:请参阅马克的答案详细解释如何以编程方式做到这一点。
这是在客户端的东西?
如果是这样,您需要创build一个WsHttpBinding和一个EndpointAddress的实例,然后将这两个传递给以这两个参数为代理的客户端构造函数。
// using System.ServiceModel; WSHttpBinding binding = new WSHttpBinding(); EndpointAddress endpoint = new EndpointAddress(new Uri("http://localhost:9000/MyService")); MyServiceClient client = new MyServiceClient(binding, endpoint);
如果它在服务器端,则需要以编程方式创build自己的ServiceHost实例,并向其中添加适当的服务端点。
ServiceHost svcHost = new ServiceHost(typeof(MyService), null); svcHost.AddServiceEndpoint(typeof(IMyService), new WSHttpBinding(), "http://localhost:9000/MyService");
当然,您可以将多个服务端点添加到您的服务主机。 完成之后,您需要通过调用.Open()方法来打开服务主机。
如果您希望能够在运行时dynamicselect要使用的configuration,则可以定义多个configuration,每个configuration都有唯一的名称,然后使用configuration调用相应的构造函数(用于服务主机或代理客户机)你想使用的名字。
例如,您可以轻松地拥有:
<endpoint address="http://mydomain/MyService.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IASRService" contract="ASRService.IASRService" name="WSHttpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="https://mydomain/MyService2.svc" binding="wsHttpBinding" bindingConfiguration="SecureHttpBinding_IASRService" contract="ASRService.IASRService" name="SecureWSHttpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint> <endpoint address="net.tcp://mydomain/MyService3.svc" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IASRService" contract="ASRService.IASRService" name="NetTcpBinding_IASRService"> <identity> <dns value="localhost" /> </identity> </endpoint>
(三个不同的名称,通过指定不同的bindingConfigurations不同的参数),然后select正确的实例化您的服务器(或客户端代理)。
但是,在这两种情况下(服务器和客户端),您必须在实际创build服务主机或代理客户端之前select。 一旦创build,这些是不可变的 – 一旦他们启动和运行,你不能调整它们。
渣子
我使用下面的代码来更改App.Config文件中的端点地址。 您可能需要在使用前修改或删除名称空间。
using System; using System.Xml; using System.Configuration; using System.Reflection; //... namespace Glenlough.Generations.SupervisorII { public class ConfigSettings { private static string NodePath = "//system.serviceModel//client//endpoint"; private ConfigSettings() { } public static string GetEndpointAddress() { return ConfigSettings.loadConfigDocument().SelectSingleNode(NodePath).Attributes["address"].Value; } public static void SaveEndpointAddress(string endpointAddress) { // load config document for current assembly XmlDocument doc = loadConfigDocument(); // retrieve appSettings node XmlNode node = doc.SelectSingleNode(NodePath); if (node == null) throw new InvalidOperationException("Error. Could not find endpoint node in config file."); try { // select the 'add' element that contains the key //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", key)); node.Attributes["address"].Value = endpointAddress; doc.Save(getConfigFilePath()); } catch( Exception e ) { throw e; } } public static XmlDocument loadConfigDocument() { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(getConfigFilePath()); return doc; } catch (System.IO.FileNotFoundException e) { throw new Exception("No configuration file found.", e); } } private static string getConfigFilePath() { return Assembly.GetExecutingAssembly().Location + ".config"; } } }
SomeServiceClient client = new SomeServiceClient(); var endpointAddress = client.Endpoint.Address; //gets the default endpoint address EndpointAddressBuilder newEndpointAddress = new EndpointAddressBuilder(endpointAddress); newEndpointAddress.Uri = new Uri("net.tcp://serverName:8000/SomeServiceName/"); client = new SomeServiceClient("EndpointConfigurationName", newEndpointAddress.ToEndpointAddress());
我是这样做的。 好的是,它仍然从configuration中获取剩余的端点绑定设置,并仅replaceURI 。
这短代码为我工作:
Configuration wConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); ServiceModelSectionGroup wServiceSection = ServiceModelSectionGroup.GetSectionGroup(wConfig); ClientSection wClientSection = wServiceSection.Client; wClientSection.Endpoints[0].Address = <your address>; wConfig.Save();
当然你必须在configuration发生改变后创buildServiceClient代理。 您还需要引用System.Configuration和System.ServiceModel程序集以使其工作。
干杯
我修改并扩展了Malcolm Swaine的代码,通过它的name属性来修改特定的节点,并修改外部configuration文件。 希望它有帮助。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Reflection; namespace LobbyGuard.UI.Registration { public class ConfigSettings { private static string NodePath = "//system.serviceModel//client//endpoint"; private ConfigSettings() { } public static string GetEndpointAddress() { return ConfigSettings.loadConfigDocument().SelectSingleNode(NodePath).Attributes["address"].Value; } public static void SaveEndpointAddress(string endpointAddress) { // load config document for current assembly XmlDocument doc = loadConfigDocument(); // retrieve appSettings node XmlNodeList nodes = doc.SelectNodes(NodePath); foreach (XmlNode node in nodes) { if (node == null) throw new InvalidOperationException("Error. Could not find endpoint node in config file."); //If this isnt the node I want to change, look at the next one //Change this string to the name attribute of the node you want to change if (node.Attributes["name"].Value != "DataLocal_Endpoint1") { continue; } try { // select the 'add' element that contains the key //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", key)); node.Attributes["address"].Value = endpointAddress; doc.Save(getConfigFilePath()); break; } catch (Exception e) { throw e; } } } public static void SaveEndpointAddress(string endpointAddress, string ConfigPath, string endpointName) { // load config document for current assembly XmlDocument doc = loadConfigDocument(ConfigPath); // retrieve appSettings node XmlNodeList nodes = doc.SelectNodes(NodePath); foreach (XmlNode node in nodes) { if (node == null) throw new InvalidOperationException("Error. Could not find endpoint node in config file."); //If this isnt the node I want to change, look at the next one if (node.Attributes["name"].Value != endpointName) { continue; } try { // select the 'add' element that contains the key //XmlElement elem = (XmlElement)node.SelectSingleNode(string.Format("//add[@key='{0}']", key)); node.Attributes["address"].Value = endpointAddress; doc.Save(ConfigPath); break; } catch (Exception e) { throw e; } } } public static XmlDocument loadConfigDocument() { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(getConfigFilePath()); return doc; } catch (System.IO.FileNotFoundException e) { throw new Exception("No configuration file found.", e); } } public static XmlDocument loadConfigDocument(string Path) { XmlDocument doc = null; try { doc = new XmlDocument(); doc.Load(Path); return doc; } catch (System.IO.FileNotFoundException e) { throw new Exception("No configuration file found.", e); } } private static string getConfigFilePath() { return Assembly.GetExecutingAssembly().Location + ".config"; } }
}
这是您可以用来更新应用程序configuration文件的最短代码,即使没有定义configuration部分:
void UpdateAppConfig(string param) { var doc = new XmlDocument(); doc.Load("YourExeName.exe.config"); XmlNodeList endpoints = doc.GetElementsByTagName("endpoint"); foreach (XmlNode item in endpoints) { var adressAttribute = item.Attributes["address"]; if (!ReferenceEquals(null, adressAttribute)) { adressAttribute.Value = string.Format("http://mydomain/{0}", param); } } doc.Save("YourExeName.exe.config"); }
MyServiceClient client = new MyServiceClient(binding, endpoint); client.Endpoint.Address = new EndpointAddress("net.tcp://localhost/webSrvHost/service.svc"); client.Endpoint.Binding = new NetTcpBinding() { Name = "yourTcpBindConfig", ReaderQuotas = XmlDictionaryReaderQuotas.Max, ListenBacklog = 40 }
在configuration中修改configuration或绑定信息中的uri非常容易。 这是你想要的吗?
你可以这样做:
- 将您的设置保存在单独的xml文件中,并在为您的服务创build代理时通读它。
例如,我想在运行时修改我的服务端点地址,所以我有以下ServiceEndpoint.xml文件。
<?xml version="1.0" encoding="utf-8" ?> <Services> <Service name="FileTransferService"> <Endpoints> <Endpoint name="ep1" address="http://localhost:8080/FileTransferService.svc" /> </Endpoints> </Service> </Services>
-
为了阅读你的XML:
var doc = new XmlDocument(); doc.Load(FileTransferConstants.Constants.SERVICE_ENDPOINTS_XMLPATH); XmlNodeList endPoints = doc.SelectNodes("/Services/Service/Endpoints"); foreach (XmlNode endPoint in endPoints) { foreach (XmlNode child in endPoint) { if (child.Attributes["name"].Value.Equals("ep1")) { var adressAttribute = child.Attributes["address"]; if (!ReferenceEquals(null, adressAttribute)) { address = adressAttribute.Value; } } } }
-
然后在运行时获取您的客户端的web.config文件,并将服务端点地址分配为:
Configuration wConfig = ConfigurationManager.OpenMappedExeConfiguration(new ExeConfigurationFileMap { ExeConfigFilename = @"C:\FileTransferWebsite\web.config" }, ConfigurationUserLevel.None); ServiceModelSectionGroup wServiceSection = ServiceModelSectionGroup.GetSectionGroup(wConfig); ClientSection wClientSection = wServiceSection.Client; wClientSection.Endpoints[0].Address = new Uri(address); wConfig.Save();
对于它的价值,我需要更新我的RESTFul服务的SSL的端口和scheme。 这就是我所做的。 道歉,这是多一点原来的问题,但希望有用的人。
// Don't forget to add references to System.ServiceModel and System.ServiceModel.Web using System.ServiceModel; using System.ServiceModel.Configuration; var port = 1234; var isSsl = true; var scheme = isSsl ? "https" : "http"; var currAssembly = System.Reflection.Assembly.GetExecutingAssembly().CodeBase; Configuration config = ConfigurationManager.OpenExeConfiguration(currAssembly); ServiceModelSectionGroup serviceModel = ServiceModelSectionGroup.GetSectionGroup(config); // Get the first endpoint in services. This is my RESTful service. var endp = serviceModel.Services.Services[0].Endpoints[0]; // Assign new values for endpoint UriBuilder b = new UriBuilder(endp.Address); b.Port = port; b.Scheme = scheme; endp.Address = b.Uri; // Adjust design time baseaddress endpoint var baseAddress = serviceModel.Services.Services[0].Host.BaseAddresses[0].BaseAddress; b = new UriBuilder(baseAddress); b.Port = port; b.Scheme = scheme; serviceModel.Services.Services[0].Host.BaseAddresses[0].BaseAddress = b.Uri.ToString(); // Setup the Transport security BindingsSection bindings = serviceModel.Bindings; WebHttpBindingCollectionElement x =(WebHttpBindingCollectionElement)bindings["webHttpBinding"]; WebHttpBindingElement y = (WebHttpBindingElement)x.ConfiguredBindings[0]; var e = y.Security; e.Mode = isSsl ? WebHttpSecurityMode.Transport : WebHttpSecurityMode.None; e.Transport.ClientCredentialType = HttpClientCredentialType.None; // Save changes config.Save();
看看你是否把客户端部分放在正确的web.config文件中。 SharePoint有大约6到7个configuration文件。 http://msdn.microsoft.com/en-us/library/office/ms460914(v=office.14).aspx(http://msdn.microsoft.com/en-us/library/office/ms460914%28v = office.14%29.aspx )
发布这个,你可以简单地尝试
ServiceClient client = new ServiceClient("ServiceSOAP");