Winsmarts.com

Microsoft MVP

MVP Logo

Awarded the Microsoft MVP Award.

Hosted By

blah!bLaH!BLOG!!

Writing your first WCF client

Posted on 7/23/2008 @ 6:45 AM in #WCF | 13 comments | 10992 views

This is in continuation to writing your first WCF service.

Now, that you've packaged that very valuable "Hello World" functionality, you need to next write some code to check and see if you can indeed use such a service. There could be 2 situations here

a) You have pre-distributed the metadata as a definition of the interface, or a dll that contains the IHelloWorld interface., OR

b) You expect clients to generate proxies on the fly, by using the metadata that you expose using the mex end point.

 

Y'know, option #b is  simpler, so I'm gonna talk about that first.

  1. Go ahead and create a new console app.
  2. Add a new service reference to http://localhost:8731/Design_Time_Addresses/MyServices/HelloWorld/mex .. which incidently was the same endpoint address that you were exposing the metadata endpoint at. Call this new reference, the "HelloWorldReference".
  3. Go write some code, like this -
  4.    1: static void Main(string[] args)
       2: {
       3:     HelloWorldReference.HelloWorldClient client = 
       4:         new HelloWorldClient.HelloWorldClient();
       5:     Console.WriteLine(client.SayHello("Sahil"));
       6:     client.Close();
       7:     Console.Read();
       8: }
  5. Now, make sure that your service that you wrote per this article is running ..
  6. Hit F5 to run the client, here are the results -

Note: There is a bug in the generated code in the Reference.cs . Apparently, they didn't use best practices while generating the Reference.cs, and if your consoleapp name happens to be the same as ServiceName+"Client", then you get a compilation error - because of a name clash between the proxy name, and generated class name. Simply use the "global::" keyword to get rid of that error.

The error text is -

The type name 'HelloWorldReference' does not exist in the type 'HelloWorldClient.HelloWorldReference.HelloWorldClient'

Now, lets look at option #a - where you don't want to expose metadata, but instead, you have pre-distributed the contract to your clients as a DLL.

Well, in such a scenario, use the following steps -

  1. Add a reference to the contract dll.
  2. Write code as below:
  3.    1: static void Main(string[] args)
       2: {
       3:     IHelloWorld helloWorld = 
       4:         ChannelFactory<IHelloWorld>.CreateChannel(
       5:         new WSHttpBinding(), new 
       6:             EndpointAddress(
       7:             "http://localhost:8731/Design_Time_Addresses/MyServices/HelloWorld/"
       8:             ));
       9:     Console.WriteLine(helloWorld.SayHello("Sahil"));
      10: }

    What that code does, is that it first creates an instance of the client channel using the CreateChannel method, and then it can use that channel to merrily call whatever methods it wishes to - as defined by the interface.
     
    Run the app, you should see the same results as before.

Now, the above code .. especially the first line, is an eye sore. More than an eyesore, you are embedding hardcoded locations for end points inside your code. Not just locations, but the binding information, basically the entire endpoint information is hardcoded in code. Not good!

Luckily, you have just as much flexibility at the client, as you do at the server. Use the following steps:

  1. Create a definition of the endpoint in the app.config for the client -
  2.    1: <?xml version="1.0" encoding="utf-8" ?>
       2: <configuration>
       3:     <system.serviceModel>
       4:         <bindings />
       5:         <client>
       6:             <endpoint address="http://localhost:8731/Design_Time_Addresses/MyServices/HelloWorld/"
       7:                 binding="wsHttpBinding" bindingConfiguration="" contract="MyServices.IHelloWorld"
       8:                 name="HelloWorldSvc" />
       9:         </client>
      10:     </system.serviceModel>
      11: </configuration>

  3. Create the channel, using a proxy .. as shown in the code below:

  4.    1: static void Main(string[] args)
       2: {
       3:     ChannelFactory<IHelloWorld> helloWorldProxy = 
       4:         new ChannelFactory<IHelloWorld>("HelloWorldSvc");
       5:     helloWorldProxy.Open();
       6:     IHelloWorld helloWorld = helloWorldProxy.CreateChannel();
       7:     Console.WriteLine(helloWorld.SayHello("Sahil"));
       8:     helloWorldProxy.Close();
       9: }

  5. Run the above app, you should see the same results.

Now, I'd argue that Option #a here is a better choice. Why? because in option #a, you would have added a reference to only the interface IHelloWorld, the implementation is powered by the service host. AND, you didn't hard-tie your client to the service reference, i.e. generated proxy. In other words, the above code, will work, EVEN IF, the "mex" endpoint was missing.

_________________________________

Okay, so next we talk about hosting this service in IIS7. w00t!


On 7/23/2008 2:00:40 AM Gabriel said ..
Sahil, great article, this one and the other two about WCF services too, thanks!

There is a typo on line 4 of option b code:

HelloWorldReference.HelloWorldClient client =


new HelloWorldClient.HelloWorldReference.HelloWorldClient();

I think the first HelloWorldClient after new should not be there.

Thanks again,

Gabriel


On 7/23/2008 6:45:47 AM Sahil Malik said ..
Thanks Gabriel. It's fixed now. :)


On 8/6/2008 2:39:37 AM Sherly said ..
Great Sahil....Am a beginner and ur articles is really useful and to the point...Thanks


On 9/2/2008 7:03:02 AM SP.Murugesan said ..
How to host the service on IIS server running on Windows 2008 Server ? I need to allow more than 5 WebClient to consume simultaneously.I Succeeded on running Client & Service on the localhost.Same(uhh..) can't running on the Remote Server.any suggestion Sahil ?


On 11/16/2008 5:57:39 PM Shyam Gudi said ..
Great useful article for WCF beginners


On 11/17/2008 1:38:33 PM Dave said ..
OK, this I know, but how would you configure a client to connect to a WCF IIS Hosted service that is not on the same machine i.e. in a distributed environment? Localhost is localhost, my client is not on localhost. Please advise... Thank you


On 4/9/2009 11:19:20 AM Sahil Malik said ..
Dave - just change the web.config to point to wherever your svc is!


On 4/22/2009 4:03:04 PM Dave said ..
Lines 3 and 4 of the first code block should read


HelloWorldReference.HelloWorldClient client = new HelloWorldReference.HelloWorldClient();


as pointed out by Gabriel


On 7/1/2009 1:53:51 PM Mona said ..
Great job, very helpful. Clear and neat explanation. Thanks a ton!


On 8/18/2009 7:15:15 PM M Ramesh said ..
This is amazing material for a beginner !!!


On 9/9/2009 8:18:33 AM Vijay said ..
hey sahil


Its a great article to start with.


I have a doubt with respect to option a i.e predistributed the contract in a dll to client.In this case how will the client will be aware of the address and binding information to be used at client ?


On 11/19/2009 2:04:06 AM Dharmesh said ..
Hi sahil,


Nice and very helpful article for WCF beginner


On 11/30/2009 6:54:05 AM Razi said ..
Thanks buddy for explaining it in a really simple way.You article Rocks.

Please post your comments:


Your feedback will be submitted for moderation, and will appear after it is approved.

Name:  
Email (optional): Your email address will not be posted.
URL (optional):
Comments: HTML will be ignored, URLs will be converted to hyperlinks  
Enter the text you see in the box:
 

Site designed and maintained by Sahil Malik | All Rights Reserved. ©2007 WinSmarts.com.