我想以编程方式修改我的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>
答案 0 :(得分:95)
这是客户端吗?
如果是这样,您需要创建一个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);
如果它位于服务器端,那么您需要以编程方式创建自己的ServiceHost实例,并为其添加适当的服务端点。
ServiceHost svcHost = new ServiceHost(typeof(MyService), null);
svcHost.AddServiceEndpoint(typeof(IMyService),
new WSHttpBinding(),
"http://localhost:9000/MyService");
当然,您可以将多个服务端点添加到服务主机中。完成后,您需要通过调用.Open()方法打开服务主机。
如果您希望能够动态地 - 在运行时 - 选择要使用的配置,您可以定义多个配置,每个配置都有唯一的名称,然后调用相应的构造函数(对于您的服务主机或您的代理客户端)使用您要使用的配置名称。
E.g。你可以轻松拥有:
<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来指定不同的参数),然后选择正确的名称来实例化您的服务器(或客户端代理)。
但在这两种情况下 - 服务器和客户端 - 您必须在实际创建服务主机或代理客户端之前选择。 创建后,这些是不可变的 - 一旦启动并运行,您就无法调整它们。
马克
答案 1 :(得分:26)
我使用以下代码更改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";
}
}
}
答案 2 :(得分:11)
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());
我是这样做的。好处是仍然从配置中获取其余的端点绑定设置,只需替换URI 。
答案 3 :(得分:5)
这个简短的代码对我有用:
Configuration wConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ServiceModelSectionGroup wServiceSection = ServiceModelSectionGroup.GetSectionGroup(wConfig);
ClientSection wClientSection = wServiceSection.Client;
wClientSection.Endpoints[0].Address = <your address>;
wConfig.Save();
当然,您必须在配置更改后创建ServiceClient代理。 您还需要引用 System.Configuration 和 System.ServiceModel 程序集来实现此功能。
干杯
答案 4 :(得分:2)
我修改并扩展了Malcolm Swaine的代码,以便通过它的name属性修改特定节点,并修改外部配置文件。希望它有所帮助。
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";
}
}
}
答案 5 :(得分:2)
即使没有定义配置部分,这是用于更新应用配置文件的最短代码:
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");
}
答案 6 :(得分:1)
我认为您想要的是在运行时更换配置文件的一个版本,如果是这样的话,请创建一个配置文件的副本(也给它相应的扩展名,如.Debug或.Release),它具有正确的地址(它为您提供调试版本和运行时版本)并创建一个postbuild步骤,根据构建类型复制正确的文件。
以下是我过去使用过的postbuild事件示例,该事件使用正确的版本(调试/运行时)覆盖输出文件
copy "$(ProjectDir)ServiceReferences.ClientConfig.$(ConfigurationName)" "$(ProjectDir)ServiceReferences.ClientConfig" /Y
其中: $(ProjectDir)是配置文件所在的项目目录 $(ConfigurationName)是活动配置构建类型
修改强> 有关如何以编程方式执行此操作的详细说明,请参阅Marc的答案。
答案 7 :(得分:1)
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 }
在配置中修改配置或绑定信息中的uri非常容易。 这是你想要的吗?
答案 8 :(得分:1)
你可以这样做:
例如,我想在运行时修改我的服务端点地址,因此我有以下 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();
答案 9 :(得分:1)
为了它的价值,我需要为我的RESTFul服务更新SSL的端口和方案。这就是我做的。抱歉这是原始问题的一点,但希望对某人有用。
// 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();
答案 10 :(得分:0)
查看您是否将客户端部分放在正确的web.config文件中。 SharePoint有大约6到7个配置文件。 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");