I'm using WCF routing service and I'm trying to Implement failover, I need to add filter table backuplist programmatically, this is a sample configuration:
<system.serviceModel>
<client>
<endpoint address="http://localhost:8081/Service1" binding="basicHttpBinding"
contract="*" name="ServiceOperation1" />
<endpoint address="http://localhost:8081/Service2" binding="basicHttpBinding"
contract="*" name="ServiceOperation2" />
<endpoint address="http://localhost:8081/Service3" binding="basicHttpBinding"
contract="*" name="ServiceOperation3" />
</client>
<routing>
<filters>
<filter name="MatchAllFilter" filterType="MatchAll" />
</filters>
<filterTables>
<filterTable name="RoutingTable">
<add filterName="MatchAllFilter" endpointName="ServiceOperation1" backupList="BackUps" />
</filterTable>
</filterTables>
<backupLists>
<backupList name="BackUps">
<add endpointName="ServiceOperation2"/>
<add endpointName="ServiceOperation3" />
</backupList>
</backupLists>
</routing>
<behaviors>
<serviceBehaviors>
<behavior name="">
<routing filterTableName="RoutingTable" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="System.ServiceModel.Routing.RoutingService">
<endpoint address="binary" binding="basicHttpBinding"
contract="System.ServiceModel.Routing.IRequestReplyRouter" name="VirtualEndpoint" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/RoutingService/Router" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
I was able to add FilterTable which I found example in this question
here is my code snippet:
var routingHost = new ServiceHost(typeof(RoutingService));
var routingEp = routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, url);
var filterTable = new MessageFilterTable<IEnumerable<ServiceEndpoint>>();
filterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint>()
{
serviceoperation1Endpoint
});
routingHost.Description.Behaviors.Add(
new RoutingBehavior(new RoutingConfiguration(filterTable, false)));
routingHost.open();
so in my scenario ServiceOperation2 and ServiceOperation3 are the backup endpoints, I made lots of research I coudn't find a way to add backuplist Programmatically
any Idea how can I add backuplist to filterTable?
I ended up with this solution to dynamically generate config file
In my scenario, I load my endpoints from database and generated routing service configuration out of it,
public class MyServiceEndPoint
{
public string TypeName { get; set; }
public string Url { get; set; }
public string Name { get; set; }
}
//// generates routing service configuration section, including client enoints/filterTable/backups and routing service behavior
private void CreateRoutingConfiguration(List<MyServiceEndPoint> serviceEndpoints)
{
///// group endopints by Name, each service could have multiple endpoints ( 1 main and n backup endpoints)
var groupedEndpoitns = (from endp in serviceEndpoints
group endp by endp.Name into endpGroup
select new { ServiceName = endpGroup.Key, EndPoint = endpGroup }).ToList();
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
var serviceModelSectionGroup = System.ServiceModel.Configuration.ServiceModelSectionGroup.GetSectionGroup(config);
var routingSection = (RoutingSection)serviceModelSectionGroup.Sections["routing"];
var clientsection = (ClientSection)serviceModelSectionGroup.Sections["client"];
var bindingSection = (BindingsSection)serviceModelSectionGroup.Sections["bindings"];
var behaviorSection = (BehaviorsSection)serviceModelSectionGroup.Sections["behaviors"];
bindingSection.NetTcpBinding.Bindings.Clear();
clientsection.Endpoints.Clear();
var filterTable = new FilterTableEntryCollection() { Name = "RoutingTable" };
routingSection.Filters.Clear();
routingSection.FilterTables.Clear();
routingSection.BackupLists.Clear();
var nettcpBinding = new NetTcpBindingElement()
{
Name = "myTcpBinding",
TransferMode = TransferMode.Buffered,
MaxBufferSize = 2147483647,
MaxReceivedMessageSize = 2147483647,
SendTimeout = new TimeSpan(0, 10, 0),
ReceiveTimeout = new TimeSpan(0, 10, 0),
};
nettcpBinding.Security.Mode = SecurityMode.None;
bindingSection.NetTcpBinding.Bindings.Add(nettcpBinding);
foreach (var endpointGroup in groupedEndpoitns)
{
var backupListItem = new BackupEndpointCollection();
backupListItem.Name = endpointGroup.ServiceName + "Backup";
var filter = new FilterElement();
filter.Name = endpointGroup.ServiceName + "Filter";
filter.FilterType = FilterType.Custom;
filter.CustomType = "MyServiceContractMessageFilterType,asemblyName";
filter.FilterData = endpointGroup.EndPoint.FirstOrDefault().ClientTypeName;
routingSection.Filters.Add(filter);
int endpointCount = 0;
List<ChannelEndpointElement> channelEndpoints = new List<ChannelEndpointElement>();
foreach (var endpoint in endpointGroup.EndPoint)
{
endpointCount++;
var channelEndpoint = new ChannelEndpointElement();
channelEndpoint.Address = new Uri(endpoint.Url);
channelEndpoint.Binding = "netTcpBinding";
channelEndpoint.BindingConfiguration = "myTcpBinding";
channelEndpoint.Contract = "*";
channelEndpoint.Name = $"{endpoint.Name}EndPoint{endpointCount}";
clientsection.Endpoints.Add(channelEndpoint);
channelEndpoints.Add(channelEndpoint);
}
var firstChannelEndpoint = channelEndpoints.FirstOrDefault(); /// this endpoint will be selected as main endpoint
var filterTableItem = new FilterTableEntryElement();
filterTableItem.FilterName = filter.Name;
filterTableItem.EndpointName = firstChannelEndpoint.Name;
filterTableItem.BackupList = backupListItem.Name;
filterTable.Add(filterTableItem);
foreach (var backupEndpoints in channelEndpoints)
{
backupListItem.Add(new BackupEndpointElement() { EndpointName = backupEndpoints.Name });
routingSection.BackupLists.Add(backupListItem);
}
}
routingSection.FilterTables.Add(filterTable);
behaviorSection.ServiceBehaviors.Clear();
var behavior = new ServiceBehaviorElement();
behavior.Add(new RoutingExtensionElement() { FilterTableName = filterTable.Name });
behaviorSection.ServiceBehaviors.Add(behavior);
config.Save(ConfigurationSaveMode.Modified, false);
ConfigurationManager.RefreshSection("system.serviceModel/routing");
ConfigurationManager.RefreshSection("system.serviceModel/client");
ConfigurationManager.RefreshSection("system.serviceModel/behaviors");
}
so first I generated configuration file
and than create an intance of routing service like:
CreateRoutingConfiguration(serviceEndpoints);
routingHost = new ServiceHost(typeof(RoutingService));
routingHost.AddServiceEndpoint(typeof(System.ServiceModel.Routing.IRequestReplyRouter), mybinding, $"net.tcp://localhost:6000/Router");
routingHost.Open();
hope it will be helpful for someone
I've never done this, but a quick look through the documentation on MSDN for Message Filters shows that alternative backup endpoints are configured via the FilterTableElementEntry class (BackupList property).
A filter table is a named collection of FilterTableEntryElement
objects that define the association between a filter, a primary
destination endpoint, and a list of alternative backup endpoints. The
filter table entries also allow you to specify an optional priority
for each filter condition.
Check for Filter Table and BackupList on Google, and you'll come across examples of usage of this. This example looks particularly promising with plenty of comments describing the steps.
Related
I am developing an UWP application which consumes wcf duplex service made by myself. The problem occurs when I try to call a method from service, literally method does not firing up and no breakpoint in service code is hitted.
This is my configuration in host application
<system.serviceModel>
<services>
<service name="WcfService.Services.ImageExchangeService" behaviorConfiguration="behaviorConfig">
<endpoint address="net.tcp://localhost:4322/WcfService/Services/ImageExchangeService/tcp" binding="netTcpBinding" contract="WcfService.Services.IImageExchangeService" bindingConfiguration="tcpBinding"></endpoint>
<endpoint address="net.tcp://localhost:4323/WcfService/Services/ImageExchangeService/mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:4321/WcfService/Services/ImageExchangeService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="behaviorConfig">
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpBinding">
<security mode="None"></security>
<reliableSession enabled="true"/>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
This is my service interface
[ServiceContract(CallbackContract = typeof(IImageExchangeClient), SessionMode =SessionMode.Required)]
public interface IImageExchangeService
{
[OperationContract(IsOneWay = true)]
void Connect(string deviceIdentifier);
}
This is my implementation of above interface
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults =true)]
public class ImageExchangeService : IImageExchangeService
{
private Dictionary<string, IImageExchangeClient> _connectedDevices = new Dictionary<string, IImageExchangeClient>();
public void Connect(string deviceIdentifier)
{
var connection = OperationContext.Current.GetCallbackChannel<IImageExchangeClient>();
if (!_connectedDevices.ContainsKey(deviceIdentifier))
{
_connectedDevices.Add(deviceIdentifier, connection);
}
else
{
_connectedDevices[deviceIdentifier] = connection;
}
Console.WriteLine("\nDevice connected: {0}", deviceIdentifier);
}
}
and finally this is my UWP code where I trying to call Connect method
public async void InitializeImageExchangeClient()
{
var endpoint = new EndpointAddress(new Uri("net.tcp://localhost:4322/WcfService/Services/ImageExchangeService/tcp"));
var InstanceContext = new InstanceContext(new ImageExchangeCallback());
var client = new ImageExchangeService.ImageExchangeServiceClient(buildBinding(), endpoint);
var channelFactory = (DuplexChannelFactory<IImageExchangeService>)(client.ChannelFactory);
var proxy = channelFactory.CreateChannel(InstanceContext);
await proxy.ConnectAsync(DeviceIdentifier);
}
I have also tried other approach of cal this method like:
var client = new ImageExchangeServiceClientBase(InstanceContext, buildBinding(), endpoint);
await client.OpenAsync();
await client.ConnectAsync(DeviceIdentifier);
buildBinding() function looks like this:
private NetTcpBinding buildBinding()
{
var binding = new NetTcpBinding()
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferPoolSize = int.MaxValue,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = int.MaxValue,
MaxBytesPerRead = int.MaxValue,
MaxDepth = int.MaxValue,
MaxNameTableCharCount = int.MaxValue,
MaxStringContentLength = int.MaxValue
},
OpenTimeout = TimeSpan.MaxValue,
ReceiveTimeout = TimeSpan.MaxValue,
};
binding.Security.Mode = SecurityMode.None;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
return binding;
}
Actual result is the method Connect is not firing up, and when I toggle breakpoint on this method it is not hitted.
Other non-duplex services are working fine without a problem.
When I implemented this service in WPF application the method is calling properly and everything works fine, the problem is when I trying to implement this in UWP architecture.
Thanks for help in advance.
I have a WCF service running under .NET Framework 4.6.2. I have used the web.config before to configure the service with my custom IAuthorizationPolicy like this :
<services>
behaviorConfiguration="MyClientService.CustomValidator_Behavior" name="My.Service.Implementation.Services.MyClientService">
<endpoint binding="netHttpBinding" behaviorConfiguration="protoEndpointBehavior" address="BinaryHttpProto" bindingNamespace="http://My.ServiceContracts/2007/11" contract="My.ServiceContracts.IMyClientService" />
<endpoint binding="netHttpsBinding" behaviorConfiguration="protoEndpointBehavior" address="BinaryHttpsProto" bindingNamespace="http://My.ServiceContracts/2007/11" contract="My.ServiceContracts.IMyClientService" />
bindingConfiguration="netTcpCertificate" behaviorConfiguration="protoEndpointBehavior" bindingNamespace="http://My.ServiceContracts/2007/11" contract="My.ServiceContracts.IMyClientService" address="Sll"/>
<host>
</host>
</service>
</services>
<behavior name="MyClientService.CustomValidator_Behavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
<customBehaviorExtension_ClientService />
<serviceThrottling maxConcurrentCalls="2000" maxConcurrentSessions="2147483647" maxConcurrentInstances="2000" />
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode="PeerOrChainTrust" />
</clientCertificate>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="My.Service.Implementation.Security.CustomUsernamePasswordValidator, My.Service.Implementation" />
</serviceCredentials>
<serviceAuthorization principalPermissionMode="Custom" serviceAuthorizationManagerType="My.Service.Implementation.Security.CustomServiceAuthorizationManager, My.Service.Implementation">
<authorizationPolicies>
<add policyType="My.Service.Implementation.Security.CustomAuthorizationPolicy_ClientService, My.Service.Implementation" />
</authorizationPolicies>
</serviceAuthorization>
</behavior>
Now I need to swtich to do this in code and this is what that looks like :
var endpoint = new System.ServiceModel.Description.ServiceEndpoint(System.ServiceModel.Description.ContractDescription.GetContract(typeof(IMyClientService)),
binding,
new EndpointAddress(endPointAddress));
endpoint.EndpointBehaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());
serviceHost.AddServiceEndpoint(endpoint);
ServiceAuthorizationBehavior serviceAuthorizationBehavior = serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
if (serviceAuthorizationBehavior == null)
{
serviceAuthorizationBehavior = new ServiceAuthorizationBehavior();
serviceHost.Description.Behaviors.Add(serviceAuthorizationBehavior);
}
serviceAuthorizationBehavior.ExternalAuthorizationPolicies = new ReadOnlyCollection<IAuthorizationPolicy>(new IAuthorizationPolicy[] { new CustomAuthorizationPolicy_ClientService() });
((ServiceBehaviorAttribute)serviceHost.Description.Behaviors[typeof(ServiceBehaviorAttribute)]).MaxItemsInObjectGraph = 2147483647;
((ServiceBehaviorAttribute)serviceHost.Description.Behaviors[typeof(ServiceBehaviorAttribute)]).IncludeExceptionDetailInFaults = true;
ServiceThrottlingBehavior throttleBehavior = new ServiceThrottlingBehavior
{
MaxConcurrentCalls = 200,
MaxConcurrentInstances = 2147483647,
MaxConcurrentSessions = 2000,
};
serviceHost.Description.Behaviors.Add(throttleBehavior);
Console.WriteLine("Starting service...");
serviceHost.Open();
Console.WriteLine("Service started successfully (" + uri + ")");
return serviceHost;
}
catch(Exception ex)
In the IAuthorizationPolicy i set the principla like this just as before and it does break here :
var userContext = new UserContextOnService(new ClientIdentity { AuthenticationType = "regular", IsAuthenticated = true, Name = "username" }, currentAnvandare, LoginType.UsernamePassword);
userContext.OrbitToken = orbitToken;
evaluationContext.Properties["Principal"] = userContext;
SharedContext.Instance.AddUserContext(person.PersonId.ToString(), userContext);
The problem is that when I try to run this :
(UserContextOnService)Thread.CurrentPrincipal;
In the service method I get exception, the CurrentPrincipal is a WindowPrincipal?
I can get the correct Principal by using this code :
OperationContext.Current.ServiceSecurityContext.AuthorizationContext.Properties["Principal"]
But that would mean to change in MANY places where the context is fetched with just Thread.CurrentPrincipal.
I suspect that I have lost something in the configuration?
Edit : Have tried to set the Thread.CurrentPrincipal = userContext; in the Evaluate method but this does not help, the Thread.CurrentPrincipal if still a WindowsPrinciple? I suspect that the servicemethod is ending up on another thread then the one that executes the Evaluate.
When starting the service this needed to be set as well :
serviceAuthorizationBehavior.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
serviceAuthorizationBehavior.ServiceAuthorizationManager = new CustomServiceAuthorizationManager();
This is done right above the following line :
serviceAuthorizationBehavior.ExternalAuthorizationPolicies = new ReadOnlyCollection<IAuthorizationPolicy>(new IAuthorizationPolicy[] { new CustomAuthorizationPolicy_ClientService() });
I have a persistent problem, which I have been researching for a couple days now. I am working on transitioning a WCF service to use a dynamic port, a need has finally come into scope for this. I am most of the way there; however, I am getting the error:
System.ArgumentException: This collection already contains an address with scheme net.tcp.
I have searched online for an answer, and have only found solutions to if the scheme was http. I will provide some code, to aid those who desire to help me and others with this problem.
I have a services.development.config file. We have the app.config file separated for specific reasons within the organization.
<service name="MLITS.Pulse.Pulse" behaviorConfiguration="PulseCSBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:14613/PulseService"/>
</baseAddresses>
</host>
<endpoint name="NetTcpEndPoint"
address=""
binding="netTcpBinding"
contract="MLITS.Pulse.IPulse" />
<endpoint name="NetTcpMetadataPoint"
address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
We also have the endpoint address in a client.development.config file.
<endpoint address="net.tcp://localhost:14613/PulseService" binding="netTcpBinding"
bindingConfiguration="NetTcpEndPoint" contract="PulseService.IPulse" name="NetTcpEndPoint" />
Now it is my understanding with the method I'm using, I am able to keep the specific port number specified here, and later change it. Now the way I'm changing the port number is adding the session id to the base port number (which would be the 14613). The following code is the method that does just that.
public static void DynamicAddress()
{
int sessionIdentification = 0;
int portNumber = 0;
int newPort = 0;
string uriString = string.Empty;
sessionIdentification = Process.GetCurrentProcess().SessionId;
portNumber = 14613;
newPort = portNumber + sessionIdentification;
uriString = "net.tcp://localhost:" + newPort + "/PulseService";
//seperate the port from the rest of the service
//add the session id to the port
//put the address back together and return it
Uri uri = new Uri(uriString);
ServiceHost objServiceHost = new ServiceHost(typeof(Pulse), uri);
}
The error appears when we try and process the ServiceHost line. My question is: How do I resolve this, for it to function correctly?
Keep in mind, I have tried commenting out the base addresses in the services.development.config file, as well as the endpoint address in the client.development.config file. When doing this I have ran into other issues that were because I've commented the address out.
I have resolved the issue I was having in regards to this question. Instead of trying to assign the service host with another URI, I had to first clear the Endpoints and then add my new service endpoint. The only changes I made were to the DynamicPort method. Code Follows:
public static void DynamicAddress(
{
int sessionIdentification = 0;
int portNumber = 0;
int newPort = 0;
string uriString = string.Empty;
sessionIdentification = Process.GetCurrentProcess().SessionId;
portNumber = 14613;
newPort = portNumber + sessionIdentification;
uriString = "net.tcp://localhost:" + newPort + "/PulseService";
Uri uri = new Uri(uriString);
ServiceHost objServiceHost = new ServiceHost(typeof(Pulse));
objServiceHost.Description.Endpoints.Clear();
objServiceHost.AddServiceEndpoint(typeof(Pulse), new NetTcpBinding(), uri);
}
I'm busy writing a file server/client tool that basically uses a hosted Service to send and receive data to and from the server. Since this solution will be used by many different people, its not really advisable to have them go and edit the App.Config file for their setup. What I would like to do is change this at runtime so that the user(s) have full control over the settings to use. So, this is my App.Config file:
<system.serviceModel>
<services>
<service name="FI.ProBooks.FileSystem.FileRepositoryService">
<endpoint name="" binding="netTcpBinding"
address="net.tcp://localhost:5000"
contract="FI.ProBooks.FileSystem.IFileRepositoryService"
bindingConfiguration="customTcpBinding" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="customTcpBinding" transferMode="Streamed" maxReceivedMessageSize="20480000" />
</netTcpBinding>
</bindings>
</system.serviceModel>
What I would like to do is to change only the address (in this example, net.tcp://localhost:5000) when the application is executed. So I must be able to read the current value and display that to the user, and then take their input and save it back into that field.
The test below may help you. Essentially the steps are
Instantiate an instance of the host that reads the configuration from the .config file;
Create a new instance of EndpointAddress using the same configuration as the old one, but changing the uri and assign it to the Address property of your ServiceEndpoint.
[TestMethod]
public void ChangeEndpointAddressAtRuntime()
{
var host = new ServiceHost(typeof(FileRepositoryService));
var serviceEndpoint = host.Description.Endpoints.First(e => e.Contract.ContractType == typeof (IFileRepositoryService));
var oldAddress = serviceEndpoint.Address;
Console.WriteLine("Curent Address: {0}", oldAddress.Uri);
var newAddress = "net.tcp://localhost:5001";
Console.WriteLine("New Address: {0}", newAddress);
serviceEndpoint.Address = new EndpointAddress(new Uri(newAddress), oldAddress.Identity, oldAddress.Headers);
Task.Factory.StartNew(() => host.Open());
var channelFactory = new ChannelFactory<IFileRepositoryService>(new NetTcpBinding("customTcpBinding"), new EndpointAddress(newAddress));
var channel = channelFactory.CreateChannel();
channel.Method();
(channel as ICommunicationObject).Close();
channelFactory = new ChannelFactory<IFileRepositoryService>(new NetTcpBinding("customTcpBinding"), oldAddress);
channel = channelFactory.CreateChannel();
bool failedWithOldAddress = false;
try
{
channel.Method();
}
catch (Exception e)
{
failedWithOldAddress = true;
}
(channel as ICommunicationObject).Close();
Assert.IsTrue(failedWithOldAddress);
}
you can create the service instance providing a configuration name and endpoint. So you can use;
EndpointAddress endpoint = new EndpointAddress(serviceUri);
var client= new MyServiceClient(endpointConfigurationName,endpoint )
look at msdn article.
Here I am trying to read my service endpoint address by name from web.config
ClientSection clientSection = (ClientSection)ConfigurationManager.GetSection("system.serviceModel/client");
var el = clientSection.Endpoints("SecService"); // I don't want to use index here as more endpoints may get added and its order may change
string addr = el.Address.ToString();
Is there a way I can read end point address based on name?
Here is my web.config file
<system.serviceModel>
<client>
<endpoint address="https://....................../FirstService.svc" binding="wsHttpBinding" bindingConfiguration="1ServiceBinding" contract="abc.firstContractName" behaviorConfiguration="FirstServiceBehavior" name="FirstService" />
<endpoint address="https://....................../SecService.svc" binding="wsHttpBinding" bindingConfiguration="2ServiceBinding" contract="abc.secContractName" behaviorConfiguration="SecServiceBehavior" name="SecService" />
<endpoint address="https://....................../ThirdService.svc" binding="wsHttpBinding" bindingConfiguration="3ServiceBinding" contract="abc.3rdContractName" behaviorConfiguration="ThirdServiceBehavior" name="ThirdService" />
</client>
</system.serviceModel>
This will work clientSection.Endpoints[0];, but I am looking for a way to retrieve by name.
I.e. something like clientSection.Endpoints["SecService"], but it's not working.
This is how I did it using Linq and C# 6.
First get the client section:
var client = ConfigurationManager.GetSection("system.serviceModel/client") as ClientSection;
Then get the endpoint that's equal to endpointName:
var qasEndpoint = client.Endpoints.Cast<ChannelEndpointElement>()
.SingleOrDefault(endpoint => endpoint.Name == endpointName);
Then get the url from the endpoint:
var endpointUrl = qasEndpoint?.Address.AbsoluteUri;
You can also get the endpoint name from the endpoint interface by using:
var endpointName = typeof (EndpointInterface).ToString();
I guess you have to actually iterate through the endpoints:
string address;
for (int i = 0; i < clientSection.Endpoints.Count; i++)
{
if (clientSection.Endpoints[i].Name == "SecService")
address = clientSection.Endpoints[i].Address.ToString();
}
Well, each client-side endpoint has a name - just instantiate your client proxy using that name:
ThirdServiceClient client = new ThirdServiceClient("ThirdService");
Doing this will read the right information from the config file automatically.