I am trying to create a tool to modify my service's app.config file programmatically. The code is something like this,
string _configurationPath = @"D:\MyService.exe.config";
ExeConfigurationFileMap executionFileMap = n开发者_运维问答ew ExeConfigurationFileMap();
executionFileMap.ExeConfigFilename = _configurationPath;
System.Configuration.Configuration config = ConfigurationManager.OpenMappedExeConfiguration(executionFileMap, ConfigurationUserLevel.None);
ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);
foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints)
{
if (endpoint.Name == "WSHttpBinding_IMyService")
{
endpoint.Address = new Uri("http://localhost:8080/");
}
}
config.SaveAs(@"D:\MyService.exe.config");
However I have problem changing the endpoint's identity.
I want to have something like:
<identity>
<userPrincipalName value="user@domain.com" />
</identity>
for my endpoint configuration, but when i try :
endpoint.Identity = new IdentityElement(){
UserPrincipalName = UserPrincipalNameElement() { Value = "user@domain.com" }
}
It fails because the property endpoint.Identity and identityElement.UserPrincipalName is readonly (I'm not sure why, because entity.Address is not read-only)
Is there any way to get around this restriction and set the identity configuration?
This is confirmed as working. What a pain ...
public static void ChangeClientEnpoint(string name, Uri newAddress)
{
System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);
ChannelEndpointElement existingElement = null;
foreach (ChannelEndpointElement endpoint in serviceModeGroup.Client.Endpoints)
{
if (endpoint.Name == "BasicHttpBinding_IMembershipService")
{
existingElement = endpoint;
}
}
EndpointAddress endpointAddress = new EndpointAddress(newAddress.ToString());
var newElement = new ChannelEndpointElement(endpointAddress, existingElement.Contract)
{
BehaviorConfiguration = existingElement.BehaviorConfiguration,
Binding = existingElement.Binding,
BindingConfiguration = existingElement.BindingConfiguration,
Name = existingElement.Name
// Set other values
};
serviceModeGroup.Client.Endpoints.Remove(existingElement);
serviceModeGroup.Client.Endpoints.Add(newElement);
config.Save();
ConfigurationManager.RefreshSection("system.serviceModel/client");
}
For anyone looking for a solution to this, I believe you can achieve it with the following (this is a small extension of the previous example):
public void ChangeMyEndpointConfig(ChannelEndpointElement existingElement, ServiceModelSectionGroup grp, string identityValue)
{
EndpointAddress endpointAddress = new EndpointAddress(existingElement.Address, EndpointIdentity.CreateDnsIdentity(identityValue));
var newElement = new ChannelEndpointElement(endpointAddress, existingElement.Contract)
{
BehaviorConfiguration = existingElement.BehaviorConfiguration,
Binding = existingElement.Binding,
BindingConfiguration = existingElement.BindingConfiguration,
Name = existingElement.Name
// Set other values
};
grp.Client.Endpoints.Remove(existingElement);
grp.Client.Endpoints.Add(newElement);
}
I don't think there is a way to do this built into the framework, at least I haven't seen anything easy but could be wrong.
I did see an answer to a different question, https://stackoverflow.com/a/2068075/81251, that uses standard XML manipulation to change the endpoint address. It is a hack, but it would probably do what you want.
Below is the code from the linked answer, for the sake of completeness:
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";
}
}
}
Try something like this...
http://msdn.microsoft.com/en-us/library/bb628618.aspx
ServiceEndpoint ep = myServiceHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
String.Empty);
EndpointAddress myEndpointAdd = new EndpointAddress(new Uri("http://localhost:8088/calc"),
EndpointIdentity.CreateDnsIdentity("contoso.com"));
ep.Address = myEndpointAdd;
精彩评论