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

alc*_*cal 49 c# wcf app-config configuration-files

我想以编程方式修改我的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>
Run Code Online (Sandbox Code Playgroud)

mar*_*c_s 95

这是客户端的事吗?

如果是这样,您需要创建一个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);
Run Code Online (Sandbox Code Playgroud)

如果它位于服务器端,那么您需要以编程方式创建自己的ServiceHost实例,并为其添加适当的服务端点.

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

svcHost.AddServiceEndpoint(typeof(IMyService), 
                           new WSHttpBinding(), 
                           "http://localhost:9000/MyService");
Run Code Online (Sandbox Code Playgroud)

当然,您可以将多个服务端点添加到服务主机中.完成后,您需要通过调用.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>
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这应该是正确的答案,它更加详细和有用. (11认同)

小智 26

我使用以下代码更改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";
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 黑客与否,如果以后对使用该程序的用户不再提供支持,这可能非常有用 (3认同)

小智 11

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());
Run Code Online (Sandbox Code Playgroud)

我是这样做的.好处是它仍然从配置中获取其余的端点绑定设置,只是替换了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();
Run Code Online (Sandbox Code Playgroud)

当然,您必须在配置更改后创建ServiceClient代理.您还需要引用System.ConfigurationSystem.ServiceModel程序集以使其工作.

干杯


alm*_*ori 1

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

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

copy "$(ProjectDir)ServiceReferences.ClientConfig.$(ConfigurationName)" "$(ProjectDir)ServiceReferences.ClientConfig" /Y
Run Code Online (Sandbox Code Playgroud)

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

编辑: 请参阅马克的回答,了解如何以编程方式执行此操作的详细说明。