WCF - Dynamically calling different web service endpoints implementing the same interface - wcf

I have a number of different applications that implement the same contract. In my main app, I would like to have one proxy. Then dynamically, given a Uri for a particular application, I would create a web service request and call that. How can that be accomplished? Thanks!

Do these steps:
generate your client-side proxy based on one service
this will generate the C#/VB.NET classes for you, as well as the app.config (or web.config if your client is a web app)
when calling the default service endpoint, you can do something like:
YourServiceClient client = new YourServiceClient();
client.CallSomeMethod();
This will use all the settings from the default service endpoint as defined in your config file
if you need to provide a different endpoint, do this:
YourServiceClient client =
new YourServiceClient("default", "http://server/YourOtherService.svc");
client.CallSomeMethod();
There is an overload for the client constructor which will take two parameters: the name of the endpoint configuration in your client config file (you need to look that up after you've added the service reference), and the endpoint URL you want to connect to (which can be different from what's stored in the config).
If all the other parameters like service contract, binding information etc. stay the same, this method should work and it should allow you to connect to any number of varying endpoints using this second constructor overload.

When you instantiate the service client, you can set the uri
ReconcileSvc.ReconcileClient client = new ReconcileClient();
client.Endpoint.Address = new System.ServiceModel.EndpointAddress(uri);
Hope it helps.

Related

Referencing WCF Services without mex binding

I was wondering how a client project in Visual Studio could reference a WCF service that doesn't have a mex binding. Whenever I remove the default mex binding in any sample WCF service, the client apps cannot find the service and in the auto-generated comments, it's recommended that in production environment, mex binding should be removed. Then how are the client apps supposed to find the service and reference it?
If you have access to the assemblies which contain the types which define the service contract, operations, and data contracts, then you can just create a proxy on the fly using ChannelFactory. In this instance you would not need to retrieve any service metadata as you already have access to all the information you need to call the service.
For example
// Create service proxy on the fly
var factory = new ChannelFactory<IMyServiceContract>("NameOfMyClientEndpointInConfigFile");
var proxy = factory.CreateChannel();
// Create data contract
var requestDataContract = new MyDataContract();
// Call service operation.
var responseDataContract = proxy.MyServiceOperation(requestDataContract);
It also helps if you have access to the service-side config file so you can copy the endpoint details out of there into your client config.
The mex endpoint is a necessary part of WCF SOAP services. It is what enables client toolkits to pull down the WSDL and auto-generate proxy classes. As you point out, without it, clients have no way to get the information to consume the service. If you want clients to be able to consume and find your service, you should leave it available when your service is in production.

Configure WCF without using config file and instantiating proxy client with default constructor

I am not sure this is even possible to be honest,
I am wondering if there is a way of removing the use of the config file without having to override the creation of the client proxy. Let me give an example:
In a client app we have a WCF DAL project. This is a wrapper for their WCF Server for the client app to consume. At present the client app would need all the bindings and endpoints given in the config file and would normally (in our projects) do something like the following to wrap the WCF service:
public MyObject GetMyObject(int id)
{
using(var service = new MyObjectDataServiceClient())
{
return service.GetMyOBject(id);
}
}
This would create the call to the server and get an object back. If the client app didn't have the bindings and endpoints it would blow up. We could change each creation of the data service client to create the binding and endpoint, or create our own chanelfactory to do this for us but this means changing the current WCF DAL layer code.
My goal is to try and create a way of inserting a process into the WCF DAL layer that will handle the bindings and endpoints without the consuming code having to change, whilst removing the need for the config file.
My thoughts so far were to try and use a TT file so that it would create a partial class of the data service client and override the channel factory part. This failed because of the constructor call for the data service client goes straight into the abstract class (System.ServiceModel.ClientBase<T>) and tries to get the config stuff out. I could not find a way of stopping it looking in the config via this partial class and not changing the WCF DAL service layer.
If you have the binding and the endpoint at the DAL, you can use a different constructor of the client class (one which takes the binding + endpoint address). That constructor completely bypasses configuration, so you don't need to have anything in config.

Create WCF endpoint configurations in the client app, in code?

I am trying to consume a WCF web service from a .NET client application, and I think I need to be able to programmatically create endpoints, but I don't know how. I think I need to do this because, when I try to run the application, I am getting the following error:
Could not find default endpoint
element that references contract
'IEmailService' in the ServiceModel
client configuration section. This
might be because no configuration file
was found for your application, or
because no endpoint element matching
this contract could be found in the
client element.
While troubleshooting this error, I created a simple windows forms application, in which I try to consume the same web service. With this test application I can connect to the web service successfully, and I get a valid response. But, I can reproduce the exact error cited above within in my test app by removing the system.serviceModel node and all of its child nodes from the application's app.config file (I might not have to remove ALL of that section, I'm not sure). So, my first thought was that I need to add that section to the app.config file for the real app, and everything should be fine. Unfortunately, for ridiculous reasons that I won't get into here, that is not an option. So, I am left with having to generate this information in code, inside the client app.
I am hoping someone here can help me work through this, or can point me toward a good resource for this sort of problem.
Is it possible to create endpoint configurations in the client app, in code?
By default, when you do an Add Service Reference operation, the WCF runtime will generate the client-side proxy for you.
The simplest way to use it is to instantiate the client proxy with a constructor that takes no parameters, and just grab the info from the app.config:
YourServiceClient proxy = new YourServiceClient();
This requires the config file to have a <client> entry with your service contract - if not, you'll get the error you have.
But the client side proxy class generated by the WCF runtime also has additional constructors - one takes an endpoint address and a binding, for instance:
BasicHttpBinding binding = new BasicHttpBinding(SecurityMode.None);
EndpointAddress epa = new EndpointAddress("http://localhost:8282/basic");
YourServiceClient proxy = new YourServiceClient(binding, epa);
With this setup, no config file at all is needed - you're defining everything in code. Of course, you can also set just about any other properties of your binding and/or endpoint here in code.
An east way to consume a WCF service if you have a reference to the assembly which defines the interface, is using the System.ServiceModel.ChannelFactory class.
For example, if you would like to use BasicHttpBinding:
var emailService = ChannelFactory<IEmailService>.CreateChannel(new BasicHttpBinding(), new EndpointAddress(new Uri("http://some-uri-here.com/));
If you don't have a reference to the service assembly, then you can use one of the overloaded constructors on the generated proxy class to specify binding settings.

How to create Endpoints from app.config file in WCF?

I have a service which has one endpoint , I have defined this endpoint in app.config file.
I want to know how can I create endpoints if I have app.config in program.
Please give me an idea.
Do you have a generated proxy for your service? If so, just use the proxy client!
MyServiceClient proxy = new MyServiceClient();
Optionally, you can pass in a name for the configuration to use:
MyServiceClient proxy = new MyServiceClient("MyConfigName");
No need to do anything fancy.
If you haven't created a proxy (using "Add Service Reference" in Visual Studio or svcutil.exe on the command line), you'll need to add a reference to your assembly containing the service and data contracts, and then use
ChannelFactory<IMyService> factory = new ChannelFactory<IMyService>();
IMyService proxy = factory.CreateChannel( );
Again, for creating the channel factory, you can pass in a name of a configuration section, if you have multiple, to specify which one to use.
Also, to clarify - a client can only ever have one endpoint at any given time. The service might have multiple - but the client needs to make up its mind and connect to exactly one of those - you cannot have multiple endpoints in a client (as the title of your questions appears to imply).
Marc
If you are using Visual Studio use the WCF Service Configuration Editor (found under tools). Use this to open your config file or hosted service and then you can create your endpoints there. Any new endpoint configuration info will be saved into your app.config/web.config as appropriate

accessing WCF service through URL

I have a WCF service ( Let's say WCFService1 ) is deployed on two remote machines. Since the same service is deployed on two different machines they have common interface and common methods exposed.
WCFService1 is deployed on Machine1 and Machine2.
To consume WCF service from client machine, I have created a client app:
I have added a design time reference of WCF service (WCFService1 )( with the help of URL http://11.12.25.23/WCFService/Service1.svc).
Now I can invoke the methods exposed in the service. Up until now its fine...
Now my question is If I have to update client at run time with same service hosted in different machine with different URL ( Let's say http://12.12.24.24/WCFService/Service1.svc), How can I do that?
At present I am doing this:
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://12.12.24.24/WCFService/Service1.svc");
MyServiceClient serviceClient = new MyServiceClient(binding, address);
but whenever I use to invoke the method exposed in the service I got binding mis match error.
Have you tried invoking your client first?
eg:
MyWCFClient client = new MyWCFClient();
client.EndPoint.Address = new EndpointAddress("http://somewhere:888/here.svc");
I'd suspect, that if you look in your web.config file on Machine1, you'll see that the binding there is WSHttpBinding (or something different than BasicHttpBinding). If you change it to BasicHttpBinding (assuming that is what you really want), you'll remove this error.
How is your service configured? Show us your server-side and client-side config!
Binding mismatch means you're either not using the same binding, or some vital parameter on the binding is different - there must be something configured wrong - so show us the config!
Marc