Winsmarts.com

Microsoft MVP

MVP Logo

Awarded the Microsoft MVP Award.

Hosted By

blah!bLaH!BLOG!!

Writing the WCF Hello World App

Posted on 4/12/2008 @ 1:39 PM in #WCF | 9 comments | 4075 views

Okay first of all, you must read my "What is WCF" blogpost, where I build up to "What makes WCF so different".

But, I'll repeat the last paragraph here -

So, what makes WCF different?

  • You first think of the Contract - What am I trying to get done!?
  • Then you think of where will I host it, and what technology will I use to host it.
  • Then you worry about the nitty gritties such as authentication etc.

For the very first time, you have a communication technology, that lets you first focus on what you're trying to get done, and worry about communication later.

In keeping with that theme, let us describe my Hello World problem first.

Problem Definition: I intend to create a service, that will accept a name, and return Hello "entered name".

How do we do it? Follow these steps -

    1. Start VS2008 (duh!), and create a new "WCF Service Library" project called MyServices as shown below:


    2. Now, out of the box, this would have generated a bunch of code for you. There is some goo in App.Config, and there is a IService1.cs and a Service1.cs. Those constitute a basic running service, we are not ready to dive into that just yet, so
      1. Right click --> Delete the IService1.cs and Service1.cs files. and
      2. Clean your app.config so it looks like this -
      3.    1: <?xml version="1.0" encoding="utf-8" ?>
           2: <configuration>
           3:   <system.web>
           4:     <compilation debug="true" />
           5:   </system.web>
           6:   <system.serviceModel>
           7:     <services>
           8:     </services>
           9:     <behaviors>
          10:       <serviceBehaviors>
          11:       </serviceBehaviors>
          12:     </behaviors>
          13:   </system.serviceModel>
          14: </configuration>
      4. Great! Now, right click on your MyServices project, and choose "Add --> New Item". And choose to add a WCF Service, call it "HelloWorld". This adds two files for you -
        1. The IHelloWorld.cs file, which contains an interface called IHelloWorld, which is your Service Contract. Go ahead and change it to look like this ---
        2.    1: [ServiceContract]
             2: public interface IHelloWorld
             3: {
             4:     [OperationContract]
             5:     string SayHello(string inputName);
             6: }
        3. The HelloWorld.cs class - which contains a class called HelloWorld, which implements the interface contract. This is where the actual logic of your service will go. Go ahead and change it, to this -
        4.    1: public class HelloWorld : IHelloWorld
             2: {
             3:     #region IHelloWorld Members
             4:     public string SayHello(string inputName)
             5:     {
             6:         return "Hello " + inputName;
             7:     }
             8:     #endregion
             9: }
      5. Also, you would note that by adding the new WCF service, Visual Studio went ahead and made some changes to your app.config. (Why the heck does my class library have an App.config? - See "Why the heck does my class library have an App.Config" later). Your App.Config looks like this now --
      6.    1: <?xml version="1.0" encoding="utf-8" ?>
           2: <configuration>
           3:   <system.web>
           4:     <compilation debug="true" />
           5:   </system.web>
           6:   <system.serviceModel>
           7:     <services>
           8:       <service behaviorConfiguration="MyServices.HelloWorldBehavior"
           9:         name="MyServices.HelloWorld">
          10:         <endpoint address="" binding="wsHttpBinding" contract="MyServices.IHelloWorld">
          11:           <identity>
          12:             <dns value="localhost" />
          13:           </identity>
          14:         </endpoint>
          15:         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          16:         <host>
          17:           <baseAddresses>
          18:             <add baseAddress="http://localhost:8731/Design_Time_Addresses/MyServices/HelloWorld/" />
          19:           </baseAddresses>
          20:         </host>
          21:       </service>
          22:     </services>
          23:     <behaviors>
          24:       <serviceBehaviors>
          25:         <behavior name="MyServices.HelloWorldBehavior">
          26:           <serviceMetadata httpGetEnabled="true" />
          27:           <serviceDebug includeExceptionDetailInFaults="false" />
          28:         </behavior>
          29:       </serviceBehaviors>
          30:     </behaviors>
          31:   </system.serviceModel>
          32: </configuration>
      7. Whoaa !! That's a big change. Lets slice and dice it piece by piece.
        1. Visual Studio added a behavior called "My Services.HelloWorldBehavior" as shown below -
        2.    1: <behaviors>
             2:   <serviceBehaviors>
             3:     <behavior name="MyServices.HelloWorldBehavior">
             4:       <serviceMetadata httpGetEnabled="true" />
             5:       <serviceDebug includeExceptionDetailInFaults="false" />
             6:     </behavior>
             7:   </serviceBehaviors>
             8: </behaviors>

          This behavior adds 2 things - a) MetaDataExchange is enabled, which means, clients can generate proxies by getting the MetaData. Usually, once your service contract is frozen, i.e. the service is deployed, you want to extract a static .wsdl file that will contain the metadata, instead of having to generate metadata everytime - generating metadata everytime will waste CPU cycles.
        3. Visual Studio, also added a service tied to the behavior above, and the name of the service is "MyServices.HelloWorld". This service is shown as below -
        4.    1: <service behaviorConfiguration="MyServices.HelloWorldBehavior"
             2: name="MyServices.HelloWorld">
             3: <endpoint address="" binding="wsHttpBinding" contract="MyServices.IHelloWorld">
             4:   <identity>
             5:     <dns value="localhost" />
             6:   </identity>
             7: </endpoint>
             8: <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
             9: <host>
            10:   <baseAddresses>
            11:     <add baseAddress="http://localhost:8731/Design_Time_Addresses/MyServices/HelloWorld/" />
            12:   </baseAddresses>
            13: </host>
            14: </service>

          Here are the important things to note about this service that just got added -
          1. It contains a baseAddress definition .. i.e. this is where the service will be located .. individual endpoints can choose to append to that base address.
          2. It contains two endpoints:
            1. One that uses IHelloWorld - this is your service's endpoint. (The dns thing can be ignored for now). It uses wsHttpBinding.
            2. A mex endpoint - that enables MetaData exchange, so end clients can generate proxies on the fly by generating and getting metadata from this service.

              So note, I am worrying about addresses, and bindings AFTER I defined the contract. I can just as easily now change this binding and address to something else
    3. THATS IT! Go run the service.

Running the service, a.k.a. Why the heck does my class library have an App.config?

Okay, this is the hella cool part. You wrote the contract first - then you worried about Address and Binding, which resulted in an endpoint. But, now where can you host this service? Well ... anywhere! In fact, right inside of Visual Studio when debugging, and then in a custom host, or IIS or WAS (Windows Activation Service), if you wish. Your service implementation doesn't change - depending upon where you host it.

To host it and test it right inside of Visual Studio, just hit F5 (and this is why we need the App.Config, the cassini server uses that config file to expose the appropriate endpoints).

The WCF test client application comes up -

Go to the SayHello method, fill in the parameters, and hit Invoke - and here are the results -

 

And once you get ninja WCF debugging skills, you will undoubtedly want to dive into the actual XML requests/responses that WCF produces -

Request -

   1: <s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
   2:   <s:Header>
   3:     <a:Action s:mustUnderstand="1">http://tempuri.org/IHelloWorld/SayHello</a:Action>
   4:     <a:MessageID>urn:uuid:2fc18d15-81f3-4d47-9064-decdca04673c</a:MessageID>
   5:     <a:ReplyTo>
   6:       <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
   7:     </a:ReplyTo>
   8:   </s:Header>
   9:   <s:Body>
  10:     <SayHello xmlns="http://tempuri.org/">
  11:       <inputName>Sahil</inputName>
  12:     </SayHello>
  13:   </s:Body>
  14: </s:Envelope>

Response -

   1: <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
   2:   <s:Header>
   3:     <a:Action s:mustUnderstand="1" u:Id="_2">http://tempuri.org/IHelloWorld/SayHelloResponse</a:Action>
   4:     <a:RelatesTo u:Id="_3">urn:uuid:0e5929b6-2825-4f49-8e1a-4572bc80b5ff</a:RelatesTo>
   5:     <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
   6:       <u:Timestamp u:Id="uuid-c1cdf223-8bb1-4093-9a07-054053145b2d-11">
   7:         <u:Created>2008-04-12T17:35:44.750Z</u:Created>
   8:         <u:Expires>2008-04-12T17:40:44.750Z</u:Expires>
   9:       </u:Timestamp>
  10:       <c:DerivedKeyToken u:Id="uuid-c1cdf223-8bb1-4093-9a07-054053145b2d-7" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
  11:         <o:SecurityTokenReference>
  12:           <o:Reference URI="urn:uuid:a089ab2a-bf67-4c1c-a368-022e6fcfa6d9" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
  13:         </o:SecurityTokenReference>
  14:         <c:Offset>0</c:Offset>
  15:         <c:Length>24</c:Length>
  16:         <c:Nonce>lqGNtZhUqXf5UEjuIyf3pQ==</c:Nonce>
  17:       </c:DerivedKeyToken>
  18:       <c:DerivedKeyToken u:Id="uuid-c1cdf223-8bb1-4093-9a07-054053145b2d-8" xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc">
  19:         <o:SecurityTokenReference>
  20:           <o:Reference URI="urn:uuid:a089ab2a-bf67-4c1c-a368-022e6fcfa6d9" ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct" />
  21:         </o:SecurityTokenReference>
  22:         <c:Nonce>yMdb0tOREQIFiSgxgDk4eA==</c:Nonce>
  23:       </c:DerivedKeyToken>
  24:       <e:ReferenceList xmlns:e="http://www.w3.org/2001/04/xmlenc#">
  25:         <e:DataReference URI="#_1" />
  26:         <e:DataReference URI="#_4" />
  27:       </e:ReferenceList>
  28:       <e:EncryptedData Id="_4" Type="http://www.w3.org/2001/04/xmlenc#Element" xmlns:e="http://www.w3.org/2001/04/xmlenc#">
  29:         <e:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
  30:         <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
  31:           <o:SecurityTokenReference>
  32:             <o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/dk" URI="#uuid-c1cdf223-8bb1-4093-9a07-054053145b2d-8" />
  33:           </o:SecurityTokenReference>
  34:         </KeyInfo>
  35:         <e:CipherData>
  36:           <e:CipherValue>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</e:CipherValue>
  37:         </e:CipherData>
  38:       </e:EncryptedData>
  39:     </o:Security>
  40:   </s:Header>
  41:   <s:Body u:Id="_0">
  42:     <SayHelloResponse xmlns="http://tempuri.org/">
  43:       <SayHelloResult>Hello Sahil</SayHelloResult>
  44:     </SayHelloResponse>
  45:   </s:Body>
  46: </s:Envelope>

________________________

Great .. and now that you have written your first WCF service .. the next obvious step is, to write your first WCF client (and not use the generic WCF test client), after which, we will see, how you can host this inside of a completely different host, such as IIS.


On 4/14/2008 2:35:41 PM Chris Chandler said ..

I found this post super helpful, I am reading a couple books on wcf, and it took them both 200 pages to get where you got in 5 minutes of light reading.


On 5/2/2008 7:54:01 AM Lou said ..

This is an excellent post!! Thanks, this help me figured out a problem..


On 5/12/2008 2:51:52 AM subho100 said ..

This post is just great! Very nicely explained.


On 5/24/2008 1:52:00 AM Vivek said ..

This is a good post for the one who just started writing WCF services.

Thanks a lot.


On 5/28/2008 4:10:10 PM Daniel said ..

Excellent post. Clear and to the point.


On 6/1/2008 1:08:53 PM Sascha said ..

Great Stuff, like your refreshing writing style :-)


On 6/4/2008 8:23:20 PM Jeff said ..

Thanks for making the concepts accessible. Your blog makes an excellent companion to the intermediate/advanced materials that have been all I've had at my disposal.


On 7/4/2008 1:23:35 AM Atul said ..

Thanks a ton buddy. Really very helpfull article


On 8/7/2008 3:58:29 PM Suresh said ..

Thank you. Very nice and detailed. Good job. Keep it up.

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.