C# 如何以编程方式修改 WCF app.config 端点地址设置?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/966323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:24:22  来源:igfitidea点击:

How to programmatically modify WCF app.config endpoint address setting?

c#wcfapp-configconfiguration-files

提问by alchemical

I'd like to programmatically modify my app.config file to set which service file endpoint should be used. What is the best way to do this at runtime? For reference:

我想以编程方式修改我的 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>

采纳答案by almog.ori

I think what you want is to swap out at runtime a version of your config file, if so create a copy of your config file (also give it the relevant extension like .Debug or .Release) that has the correct addresses (which gives you a debug version and a runtime version ) and create a postbuild step that copies the correct file depending on the build type.

我认为您想要的是在运行时换出配置文件的一个版本,如果是这样,请创建具有正确地址的配置文件的副本(也给它相关的扩展名,如 .Debug 或 .Release)(这会给您一个调试版本和一个运行时版本)并创建一个 postbuild 步骤,根据构建类型复制正确的文件。

Here is an example of a postbuild event that I've used in the past which overrides the output file with the correct version (debug/runtime)

这是我过去使用的 postbuild 事件的示例,它使用正确的版本(调试/运行时)覆盖输出文件

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

where : $(ProjectDir) is the project directory where the config files are located $(ConfigurationName) is the active configuration build type

其中: $(ProjectDir) 是配置文件所在的项目目录 $(ConfigurationName) 是活动的配置构建类型

EDIT:Please see Marc's answer for a detailed explanation on how to do this programmatically.

编辑:有关如何以编程方式执行此操作的详细说明,请参阅 Marc 的回答。

回答by marc_s

Is this on the client side of things??

这是在客户端吗?

If so, you need to create an instance of WsHttpBinding, and an EndpointAddress, and then pass those two to the proxy client constructor that takes these two as parameters.

如果是这样,您需要创建一个 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);

If it's on the server side of things, you'll need to programmatically create your own instance of ServiceHost, and add the appropriate service endpoints to it.

如果它在服务器端,您需要以编程方式创建自己的 ServiceHost 实例,并向其添加适当的服务端点。

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

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

Of course you can have multiple of those service endpoints added to your service host. Once you're done, you need to open the service host by calling the .Open() method.

当然,您可以将多个服务端点添加到您的服务主机。完成后,您需要通过调用 .Open() 方法打开服务主机。

If you want to be able to dynamically - at runtime - pick which configuration to use, you could define multiple configurations, each with a unique name, and then call the appropriate constructor (for your service host, or your proxy client) with the configuration name you wish to use.

如果您希望能够在运行时动态选择要使用的配置,您可以定义多个配置,每个配置都有一个唯一的名称,然后使用配置调用适当的构造函数(对于您的服务主机或代理客户端)您希望使用的名称。

E.g. you could easily have:

例如,您可以轻松拥有:

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

(three different names, different parameters by specifying different bindingConfigurations) and then just pick the right one to instantiate your server (or client proxy).

(三个不同的名称,通过指定不同的 bindingConfigurations 来获得不同的参数),然后选择正确的一个来实例化您的服务器(或客户端代理)。

But in both cases - server and client - you have to pick before actually creating the service host or the proxy client. Once created, these are immutable- you cannot tweak them once they're up and running.

但在这两种情况下 - 服务器和客户端 - 您必须在实际创建服务主机或代理客户端之前进行选择。一旦创建,这些是不可变的- 一旦它们启动并运行,您就无法调整它们。

Marc

马克

回答by Malcolm Swaine

I use the following code to change the endpoint address in the App.Config file. You may want to modify or remove the namespace before usage.

我使用以下代码更改 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";
        }
    }
}

回答by Alex Knott

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());

I did it like this. The good thing is it still picks up the rest of your endpoint binding settings from the config and just replaces the URI.

我是这样做的。好消息是它仍然从配置中获取其余的端点绑定设置,只是替换 URI

回答by Chris - Haddox Technologies

I have modified and extended Malcolm Swaine's code to modify a specific node by it's name attribute, and to also modify an external config file. Hope it helps.

我已经修改并扩展了 Malcolm Swaine 的代码,以通过其名称属性修改特定节点,并修改外部配置文件。希望能帮助到你。

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

}

}

回答by Alexandru Dicu

This is the shortest code that you can use to update the app config file even if don't have a config section defined:

即使没有定义配置部分,这是您可以用来更新应用程序配置文件的最短代码:

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

回答by gfan

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 }

It's very easy to modify the uri in config or binding info in config. Is this what you want?

修改 config 中的 uri 或 config 中的绑定信息非常容易。这是你想要的吗?

回答by realbizkit

this short code worked for me:

这个简短的代码对我有用:

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

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

Of course you have to create the ServiceClient proxy AFTER the config has changed. You also need to reference the System.Configurationand System.ServiceModelassemblies to make this work.

当然,您必须在配置更改后创建 ServiceClient 代理。您还需要引用System.ConfigurationSystem.ServiceModel程序集来完成这项工作。

Cheers

干杯

回答by user3531280

see if you are placing the client section in the correct web.config file. SharePoint has around 6 to 7 config files. 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)

查看您是否将客户端部分放置在正确的 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)

Post this you can simply try

发布这个你可以简单地尝试

ServiceClient client = new ServiceClient("ServiceSOAP");

ServiceClient client = new ServiceClient("ServiceSOAP");

回答by Rashmi Singh

You can do it like this:

你可以这样做:

  • Keep your settings in a separate xml file and read through it when you create a proxy for your service.
  • 将您的设置保存在单独的 xml 文件中,并在为您的服务创建代理时通读它。

For example , i want to modify my service endpoint address at runtime so i have the following ServiceEndpoint.xmlfile.

例如,我想在运行时修改我的服务端点地址,所以我有以下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>
  • For reading your 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;
                }
           }
       }
    }  
    
  • Then get your web.config file of your client at runtime and assign the service endpoint address as:

        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();
    
  • 阅读您的 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();