web-dev-qa-db-fra.com

Comment modifier par programme le paramètre d'adresse de point de terminaison WCF app.config?

Je voudrais modifier par programme mon fichier app.config pour définir le point de terminaison du fichier de service à utiliser. Quelle est la meilleure façon de procéder à l'exécution? Pour référence:

<endpoint address="http://mydomain/MyService.svc"
    binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IASRService"
    contract="ASRService.IASRService" name="WSHttpBinding_IASRService">
    <identity>
        <dns value="localhost" />
    </identity>
</endpoint>
49
alchemical

Je pense que ce que vous voulez est d'échanger au moment de l'exécution une version de votre fichier de configuration, si c'est le cas, créez une copie de votre fichier de configuration (donnez-lui également l'extension appropriée comme .Debug ou .Release) qui a les bonnes adresses (ce qui vous donne une version de débogage et une version d'exécution) et créez une étape de post-construction qui copie le fichier correct en fonction du type de build.

Voici un exemple d'événement de post-construction que j'ai utilisé dans le passé et qui remplace le fichier de sortie par la bonne version (débogage/exécution)

copy "$(ProjectDir)ServiceReferences.ClientConfig.$(ConfigurationName)" "$(ProjectDir)ServiceReferences.ClientConfig" /Y

où: $ (ProjectDir) est le répertoire du projet où se trouvent les fichiers de configuration $ (ConfigurationName) est le type de build de configuration actif

EDIT: Veuillez voir la réponse de Marc pour une explication détaillée sur la façon de procéder par programmation.

1
almog.ori

Est-ce du côté client?

Si tel est le cas, vous devez créer une instance de WsHttpBinding et un EndpointAddress, puis les transmettre au constructeur du client proxy qui prend ces deux paramètres.

// using System.ServiceModel;
WSHttpBinding binding = new WSHttpBinding();
EndpointAddress endpoint = new EndpointAddress(new Uri("http://localhost:9000/MyService"));

MyServiceClient client = new MyServiceClient(binding, endpoint);

Si c'est du côté serveur, vous devrez créer par programmation votre propre instance de ServiceHost et y ajouter les points de terminaison de service appropriés.

ServiceHost svcHost = new ServiceHost(typeof(MyService), null);

svcHost.AddServiceEndpoint(typeof(IMyService), 
                           new WSHttpBinding(), 
                           "http://localhost:9000/MyService");

Bien sûr, plusieurs de ces points de terminaison de service peuvent être ajoutés à votre hôte de service. Une fois que vous avez terminé, vous devez ouvrir l'hôte de service en appelant la méthode .Open ().

Si vous voulez pouvoir choisir dynamiquement - au moment de l'exécution - quelle configuration utiliser, vous pouvez définir plusieurs configurations, chacune avec un nom unique, puis appeler le constructeur approprié (pour votre hôte de service ou votre client proxy) avec la configuration nom que vous souhaitez utiliser.

Par exemple. vous pourriez facilement avoir:

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

(trois noms différents, des paramètres différents en spécifiant différentes configurations de liaison), puis choisissez le bon pour instancier votre serveur (ou proxy client).

Mais dans les deux cas - serveur et client - vous devez choisir avant de créer réellement l'hôte de service ou le client proxy. ne fois créés, ils sont immuables - vous ne pouvez pas les modifier une fois qu'ils sont opérationnels.

Marc

95
marc_s

J'utilise le code suivant pour modifier l'adresse du point de terminaison dans le fichier App.Config. Vous souhaiterez peut-être modifier ou supprimer l'espace de noms avant utilisation.

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";
        }
    }
}
26
Malcolm Swaine
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());

Je l'ai fait comme ça. La bonne chose est qu'il reprend toujours le reste de vos paramètres de liaison de point de terminaison de la configuration et remplace simplement l'URI.

11
Alex Knott

ce code court a fonctionné pour moi:

Configuration wConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
ServiceModelSectionGroup wServiceSection = ServiceModelSectionGroup.GetSectionGroup(wConfig);

ClientSection wClientSection = wServiceSection.Client;
wClientSection.Endpoints[0].Address = <your address>;
wConfig.Save();

Bien sûr, vous devez créer le proxy ServiceClient APRÈS que la configuration a changé. Vous devez également référencer les assemblages System.Configuration et System.ServiceModel pour que cela fonctionne.

À votre santé

5
realbizkit

J'ai modifié et étendu le code de Malcolm Swaine pour modifier un nœud spécifique par son attribut de nom, et pour modifier également un fichier de configuration externe. J'espère que ça aide.

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";
    }
}

}

Il s'agit du code le plus court que vous pouvez utiliser pour mettre à jour le fichier de configuration de l'application même si aucune section de configuration n'est définie:

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");
}
2
Alexandru Dicu

Vous pouvez le faire comme ceci:

  • Conservez vos paramètres dans un fichier xml séparé et lisez-le lorsque vous créez un proxy pour votre service.

Par exemple, je souhaite modifier mon adresse de point de terminaison de service au moment de l'exécution, j'ai donc le fichier ServiceEndpoint.xml suivant.

     <?xml version="1.0" encoding="utf-8" ?>
     <Services>
        <Service name="FileTransferService">
           <Endpoints>
              <Endpoint name="ep1" address="http://localhost:8080/FileTransferService.svc" />
           </Endpoints>
        </Service>
     </Services>
  • Pour lire votre 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;
                }
           }
       }
    }  
    
  • Obtenez ensuite votre fichier web.config de votre client au moment de l'exécution et attribuez l'adresse de point de terminaison de service comme suit:

        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();
    
1
Rashmi Singh
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 }

Il est très facile de modifier l'URI dans config ou les informations de liaison dans config. c'est ce que tu veux?

1
gfan

Pour ce que ça vaut, j'avais besoin de mettre à jour le port et le schéma SSL pour mon service RESTFul. C'est ce que j'ai fait. Toutes mes excuses, c'est un peu plus que la question d'origine, mais j'espère utile à quelqu'un.

// 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();
1
Paul Bartlett

voyez si vous placez la section client dans le fichier web.config correct. SharePoint a environ 6 à 7 fichiers de configuration. http://msdn.Microsoft.com/en-us/library/office/ms460914 (v = office.14) .aspx ( http://msdn.Microsoft.com/ fr-fr/library/office/ms460914% 28v = office.14% 29.aspx )

Postez ce que vous pouvez simplement essayer

ServiceClient client = new ServiceClient("ServiceSOAP");

0
user3531280