Referencing WCF Services without mex binding - wcf

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.

Related

Need to understand the concept from a book

I am learning WCF using a book named "Window communication foundation 4: step by step". I the second chapter, there was a tutorial about developing windows service for WCF. The client communicates to the named pipe endpoint.
//WCF inside Windows service.
protected override void OnStart(string[] args)
{
productsServiceHost = new ServiceHost(typeof(ProductsServiceImpl));
NetNamedPipeBinding binding = new NetNamedPipeBinding();
productsServiceHost.AddServiceEndpoint(typeof(IProductsService),
binding, "net.pipe://localhost/ProductsServicePipe");
productsServiceHost.Open();
}
And the client has an endpoint defined in App.config
<endpoint address="net.pipe://localhost/ProductsServicePipe"
binding="netNamedPipeBinding" bindingConfiguration=""
contract="ProductsService.IProductsService"
name="NetNamedPipeBinding_IProductsService" />
I need to create a proxy object to a "Service reference" which is not the windows service I mentioned earlier.
// Create a proxy object and connect to the service
// There service reference for "ProductsServiceClient" is
// "http://localhost:51397/ProductsService/Service.svc"
ProductsServiceClient proxy = new ProductsServiceClient("NetNamedPipeBinding_IProductsService");
Without "ProductsServiceClient", I could not initiate the proxy. Why do I need to that service reference, as I connect to a window service. I could not understand the concept clearly.
In this case the term service is being used in two senses. You have the windows service which is the host for the WCF service. The reason that you had to create a service reference was so that your project could generate all off the code necessary to create a proxy to communicate with the WCF service. As an alternative to adding a service reference you could also have used a Channel Factory. The key thing to understand is that when you are creating a WCF service you generally access that service through the WCF pipeline (via a proxy or a channel factory), even if you are doing so from the project where it is defined.
If it is the case that you are unclear about how to generate a proxy for self hosted WCF service, you should look into how svcutil.exe can used to generate proxies for compiled services.

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.

WCF proxy: Do I need to create a new and different proxy for each binding?

Let's say that I have created a WCF proxy from a WCF service (which is configured with wsHttpBinding) using Add Service (in Visual Studio 2008).
Later I want to use basicHttpBinding so I'll go and change the WCF service to use basicHttpBinding. But what about the WCF proxy? Can I just change this via Web.config or do I need to create the WCF proxy again from the WCF service via Add Service?
Thanks
It depends :-)
If you already have all the bindings in place when you do the Add Service Reference the first time around, then your client side proxy configuration will include all the bindings, and you can basically switch from using one to the other without any reconfiguration or anything. Each client endpoint (which has one specific binding) should have a name, so you can pick and choose:
MyServiceClient client = new MyServiceClient("endpointname");
However, if you add the second binding to your service after you've added the service reference to your client side code, then yes - you need to upgrade your service reference. To do so, open the Service References node in your solution explorer in the client side project, right click on that service reference you're interested in, and choose Update Service Reference from the context menu.
This will pull down any new information about additional bindings and stuff from the server side and update your client side config accordingly.
Once that's done, you should have multiple client side endpoints in your config and you can create whichever one of those is appropriate for your current needs based on the client endpoint name.

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