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 | 4 comments | 3742 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 ?

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.