How to programmatically connect a client to a WCF service?
You'll have to use the ChannelFactory class.
Here's an example:
var myBinding = new BasicHttpBinding();
var myEndpoint = new EndpointAddress("http://localhost/myservice");
using (var myChannelFactory = new ChannelFactory<IMyService>(myBinding, myEndpoint))
{
IMyService client = null;
try
{
client = myChannelFactory.CreateChannel();
client.MyServiceOperation();
((ICommunicationObject)client).Close();
myChannelFactory.Close();
}
catch
{
(client as ICommunicationObject)?.Abort();
}
}
Related resources:
- How to: Use the ChannelFactory
Programmatically have Client application list a WCF service's Endpoints created during runtime using a URL (like WCF Test Client does)
Provided that we have the service metadata URI, we could use MetadataExchangeClientMode and MetadataResolver class which is provided in the System.ServiceModel.Description namespace to retrieve and process the metadata.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-metadataresolver-to-obtain-binding-metadata-dynamically
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-use-metadataexchangeclient-to-retrieve-metadata
I have made a simple example, wish it is useful to you.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://10.157.13.69:3336/mex");
MetadataExchangeClient client = new MetadataExchangeClient(uri, MetadataExchangeClientMode.MetadataExchange);
MetadataSet metadata = client.GetMetadata();
WsdlImporter importer = new WsdlImporter(metadata);
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();
//ServiceEndpointCollection endpoints = MetadataResolver.Resolve(typeof(IService), uri, MetadataExchangeClientMode.MetadataExchange);
foreach (var item in endpoints)
{
Console.WriteLine(item.Address.Uri);
}
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string SayHello();
}
Result
Programmatically create WCF Client
Error 1 'Proxy<...>': cannot declare instance members in a static class
Look at the class that this method is inside and make sure it's not static
.
Error 3 The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
When you see a definition for a generic class like ChannelFactory<T>
or List<T>
, T
is just a placeholder for the actual type, like List<string>
or List<DateTime>
. From looking at the code above I'm guessing it's ChannelFactory<IReportData>
.
Here's a really simple client. I used the sample service that gets created whenever you make a new WCF application project.
public class MyServiceClient : ClientBase<IService>, IService
{
public string GetData(int value)
{
return base.Channel.GetData(value);
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
return base.Channel.GetDataUsingDataContract(composite);
}
}
From the documentation for ChannelFactory
:
The generic ChannelFactory class is used in advanced
scenarios that require the creation of a channel factory that can be
used to create more than one channel.
In other words, if you're just trying to create a client then you probably don't need to use ChannelFactory
.
In practice, I use Castle Windsor WCF Integration Facility to create my WCF clients. That's only applicable if you're interested in using dependency injection and working with Castle Windsor. I highly recommend learning to work with it just because dependency injection is a useful practice. But then in addition to that you get the convenience of using it to create and dispose your clients.
The result is that your classes never "know" about the WCF service. They just know that they're using IReportData
. They have no idea that the implementation of that interface is a WCF client. Behind the scenes Windsor is creating and disposing the client, and in most cases the only configuration is a one-line <endpoint>
element in your app.config.
Here's the entry page for their documentation.
Programmatically adding an endpoint
To create endpoints and bindings programmatically, you could do this on the service:
ServiceHost _host = new ServiceHost(typeof(TestService), null);
var _basicHttpBinding = new System.ServiceModel.basicHttpBinding();
//Modify your bindings settings if you wish, for example timeout values
_basicHttpBinding.OpenTimeout = new TimeSpan(4, 0, 0);
_basicHttpBinding.CloseTimeout = new TimeSpan(4, 0, 0);
_host.AddServiceEndpoint(_basicHttpBinding, "http://192.168.1.51/TestService.svc");
_host.Open();
You could also define multiple endpoints in your service config, and choose which one to connect to dynamically at run time.
On the client program you would then do this:
basicHttpBinding _binding = new basicHttpBinding();
EndpointAddress _endpoint = new EndpointAddress(new Uri("http://192.168.1.51/TestService.svc"));
TestServiceClient _client = new TestServiceClient(_binding, _endpoint);
_client.BlahBlah();
WCF - how programmatically set bindingconfiguration?
done work code so:
InstanceContext context = new InstanceContext(new ChatClient(numberclient));
NetPeerTcpBinding binding = new NetPeerTcpBinding();
EndpointAddress endpoint = new EndpointAddress("net.p2p://ChangingName123/FileServer");
binding.Resolver.Custom.Address = new EndpointAddress("net.tcp://191.14.3.11/FileServer");
binding.Security.Mode = SecurityMode.None;
NetTcpBinding ntcp = new NetTcpBinding();
ntcp.Security.Mode = SecurityMode.None;
binding.Resolver.Custom.Binding = ntcp;
factory = new DuplexChannelFactory<IChatChannel>(context, binding, endpoint);
channel = factory.CreateChannel();
WCF programmatic incorporation of service endpoint address
You can programmatically configure your endpoint. See:
http://msdn.microsoft.com/en-us/library/ff647110.aspx
This stack post covers detecting if a port is free:
In C#, how to check if a TCP port is available?
Here's another link with some programmatic endpoint configuration:
http://en.csharp-online.net/WCF_Essentials%E2%80%94Programmatic_Endpoint_Configuration
So, something like:
string svcUri = String.Format("net.tcp://localhost:{0}", port);
ServiceHost host = new ServiceHost(typeof(MyService));
Binding tcpBinding = new NetTcpBinding( );
host.AddServiceEndpoint(typeof(IMyOtherContract),tcpBinding,
svcUri);
host.Open( );
Related Topics
Does Parallel.Foreach Limit the Number of Active Threads
Best Way in .Net to Manage Queue of Tasks on a Separate (Single) Thread
.Net: Determine the Type of "This" Class in Its Static Method
How to Hide Tabpage from Tabcontrol
Pass-Through Mouse Events to Parent Control
JSON Convert Empty String Instead of Null
How to Delete Cookies from Windows.Form
Strip the Byte Order Mark from String in C#
ASP.NET Core MVC:How to Get Raw JSON Bound to a String Without a Type
Service Hangs Up at Waitforexit After Calling Batch File
How to Kill a Thread Instantly in C#
Reading Excel File Using Oledb Data Provider
How to Stop Backgroundworker Correctly
Find Recursive Group Membership (Active Directory) Using C#
Splitting a String/Number Every Nth Character/Number
How to Deploy Application with SQL Server Database on Clients