Как программно изменить настройку адреса конечной точки 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>
Ответы
Ответ 1
Я думаю, что вы хотите поменять время исполнения версии вашего файла конфигурации, если это так, создайте копию вашего файла конфигурации (также укажите ему соответствующее расширение, например .Debug или .Release), в котором указаны правильные адреса ( который дает вам отладочную версию и версию исполнения) и создайте шаг postbuild, который копирует правильный файл в зависимости от типа сборки.
Вот пример события postbuild, которое я использовал в прошлом, которое переопределяет выходной файл с правильной версией (debug/runtime)
copy "$(ProjectDir)ServiceReferences.ClientConfig.$(ConfigurationName)" "$(ProjectDir)ServiceReferences.ClientConfig" /Y
где:
$ (ProjectDir) - это каталог проекта, в котором расположены файлы конфигурации
$ (ConfigurationName) - это тип конфигурации активной конфигурации
EDIT:
См. Ответ Marc для подробного объяснения того, как это сделать программно.
Ответ 2
Это на стороне клиента?
Если это так, вам нужно создать экземпляр 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().
Если вы хотите иметь возможность динамически - во время выполнения - выберите, какую конфигурацию использовать, вы можете определить несколько конфигураций, каждый с уникальным именем, а затем вызвать соответствующий конструктор (для вашего хоста службы или вашего прокси-клиента) с именем конфигурации, которое вы хотите использовать.
например. вы можете легко:
<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>
(три разных имени, разные параметры, указав различные привязкиConfigurations), а затем просто выберите правильный, чтобы создать экземпляр вашего сервера (или клиентского прокси).
Но в обоих случаях - сервер и клиент - вы должны выбрать до фактического создания хоста службы или прокси-клиента. После создания они являются неизменяемыми - вы не можете их подстроить после их запуска.
Марк
Ответ 3
Я использую следующий код для изменения адреса конечной точки в файле 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";
}
}
}
Ответ 4
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.
Ответ 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, чтобы сделать эту работу.
Приветствия
Ответ 6
Я изменил и расширил код Malcolm Swaine, чтобы изменить конкретный node его атрибут 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";
}
}
}
Ответ 7
Это самый короткий код, который вы можете использовать для обновления файла конфигурации приложения, даже если у него нет определенного раздела конфигурации:
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");
}
Ответ 8
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 в конфигурации или информации привязки в config.
Это то, что вы хотите?
Ответ 9
Вы можете сделать это следующим образом:
- Сохраняйте свои настройки в отдельном XML файле и просматривайте его при создании прокси-сервера для вашей службы.
Например, я хочу изменить адрес конечной точки службы во время выполнения, поэтому у меня есть следующий файл 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();
Ответ 10
Для чего мне стоит обновить порт и схему SSL для моей службы RESTFul. Это то, что я сделал. Извиняется, что это немного больше, чем оригинальный вопрос, но, надеюсь, полезный для кого-то.
// 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();
Ответ 11
посмотрите, размещаете ли вы клиентский раздел в правильном файле 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");