Как программно изменить конфигурацию идентификации конечной точки? - PullRequest
2 голосов
/ 12 сентября 2011

Я пытаюсь создать инструмент для программного изменения файла app.config моей службы. Код примерно такой,

string _configurationPath = @"D:\MyService.exe.config";
ExeConfigurationFileMap executionFileMap = new 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");

Однако у меня проблема с изменением идентификатора конечной точки.

Я хочу что-то вроде:

<identity>
     <userPrincipalName value="user@domain.com" />
</identity>

для моей конфигурации конечной точки, но когда я пытаюсь:

endpoint.Identity = new IdentityElement(){
    UserPrincipalName = UserPrincipalNameElement() { Value = "user@domain.com" }
}

Сбой, потому что свойство endpoint.Identity и identityElement.UserPrincipalName доступно только для чтения (я не уверен почему, потому что entity.Address не только для чтения)

Есть ли способ обойти это ограничение и установить конфигурацию идентификации?

Ответы [ 4 ]

7 голосов
/ 16 мая 2013

Это подтверждается как работающее. Какая боль ...

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");
    }
2 голосов
/ 07 марта 2013

Для тех, кто ищет решение этой проблемы, я считаю, что вы можете достичь его с помощью следующего (это небольшое расширение предыдущего примера):

    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);
    }
1 голос
/ 08 декабря 2011

Я не думаю, что есть способ сделать это встроенным в фреймворк, по крайней мере, я не видел ничего легкого, но могу ошибаться.

Я видел ответ на другой вопрос,https://stackoverflow.com/a/2068075/81251,, который использует стандартные манипуляции XML для изменения адреса конечной точки.Это взлом, но он, вероятно, будет делать то, что вы хотите.

Ниже приведен код из связанного ответа, для полноты:

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";
        }
    }
}
0 голосов
/ 12 сентября 2011

Попробуйте что-то вроде этого ...

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;
...