Chapter 38. Windows Communication Foundation

Programmers have long been able to have one program to call routines provided by another program that is running either on the local computer or some other computer on the same network. The omnipresent Internet extended this capability to new and greater levels, allowing a client program to call service routines provided by a server that could be physically on the other side of the world.

New web technologies such as Simple Object Access Protocol (SOAP) made it easy enough to build web services for use by other programs over the Internet. This gave rise to a whole new type of application that implements a significant amount of its functionality by calling services. Because these programs focus on the use of services, this design is called service-oriented architecture (SOA).

Windows Communication Foundation (WCF) is a set of classes and tools in .NET Framework 3.0 that make it easier to build SOA applications. It includes attribute classes that let you easily mark pieces of a server application to publish services for use by clients. It also includes tools to automatically generate the Visual Basic code you need to use or consume the services.

WCF is quite large and very flexible. It gives you the ability to write secure, reliable services that support transactions and can use a variety of transport methods. For example, clients and services can communicate using HTTP or TCP network protocols, or named pipes or message queues on the local computer.

Because WCF is so flexible, there isn't space to cover it all here. Instead, this chapter provides an overview of the main concepts behind WCF, and describes a simple example client and server implementation.

WCF CONCEPTS

WCF is based on the concept of messages. A message contains some sort of communication between a client and a service. Note that the program doesn't need to deal directly with messages. It can issue subroutine and function calls just as if it were calling a local object's methods. The WCF library routines convert the call into a message and send it to the recipient transparently.

An endpoint is a place where messages are sent or received. Typically, a service creates endpoints to receive request messages from clients and clients create endpoints to initiate those requests.

Endpoints define the characteristics of the communication. They determine the number and types of parameters passed to a request and the type of any returned data. They determine whether the communication uses a request-reply, one-way, or duplex style of communication. The definition of the message format is called its service contract.

The message definitions at the endpoints at the two ends of a communication must agree. They must satisfy the same service contract. If a client sends a message in one format, but the service expects the message in a different format, the communication won't work. WCF provides tools that help you define service endpoints and automatically generate Visual Basic code to properly use corresponding client endpoints.

After you have built the client and server, the two pass messages between their endpoints following the rules of the service contract. For example, if the contract indicates that the communication is one-way, the client invokes service subroutines that do not return any data. If the communication has a request-reply style, the client invokes service functions that return some sort of reply. If the contract indicates duplex communication, then the client can call service subroutines and the server can invoke client callbacks. For example, the client can tell the service that it is interested in certain events such as stock price updates, and then the service can call the client as the updates are available.

The following sections describe a concrete example that implements a simple client and server.

WCF EXAMPLE

To build a service from scratch, you follow the steps outlined in the following list:

  1. Define the service contract in a Visual Basic interface.

  2. Implement the service contract in a service class.

  3. Build the host application to run the service.

  4. Configure the service to specify bindings and endpoints.

  5. Run the service.

After you build the service, you follow these steps to build a client:

  1. Use the SvcUtil tool to discover information about the service contract and build Visual Basic code to implement a client class.

  2. Write the client application that uses the client class.

These steps are somewhat involved and require that you know a lot about service configuration files and tools such as SvcUtil.exe. Fortunately, Visual Basic provides some application templates that make building a simple service much easier.

BUILDING THE INITIAL SERVICE

To build a service, open the File menu and select New Project. Under the Visual Basic project type, select the WCF category. Click the WCF Service Library template, enter a meaningful project name, and click OK.

Initially, Visual Basic creates an interface named IService1 shown in the following code to define the service's contract:

' NOTE: You can use the "Rename" command on the "Refactor" menu to
' change the interface name "IService1" in both code and config file together.
<ServiceContract()>
Public Interface IService1

   <OperationContract()>
   Function GetData(ByVal value As Integer) As String

   <OperationContract()>
   Function GetDataUsingDataContract(ByVal composite As CompositeType)
      As CompositeType

 ' TODO: Add your service operations here
End Interface

This interface defines two methods decorated by OperationContract attributes to identify them as methods that the service will expose to clients.

The GetData function takes an integer parameter and returns a string result. This function demonstrates a simple service method that uses standard Visual Basic data types.

The GetDataUsingDataContract function takes an object of class CompositeType as a parameter and returns another object of the same class. This function demonstrates a slightly more complicated function that works with a program-defined data type.

The following code shows the initial implementation of the service class:

' NOTE: You can use the "Rename" command on the "Refactor" menu to
' change the class name "Service1" in both code and config file together.
Public Class Service1
    Implements IService1

    Public Function GetData(ByVal value As Integer) As String _
    Implements IService1.GetData
        Return String.Format("You entered: {0}", value)
    End Function

    Public Function GetDataUsingDataContract(
     ByVal composite As CompositeType) As CompositeType _
     Implements IService1.GetDataUsingDataContract
        If composite Is Nothing Then
            Throw New ArgumentNullException("composite")
        End If
        If composite.BoolValue Then
            composite.StringValue &= "Suffix"
        End If
        Return composite
    End Function
End Class

The class Service1 implements the IService1 interface. The GetData method simply returns a string echoing its numeric parameter. The GetDataUsingDataContract method modifies its CompositeType parameter's StringValue property and returns its parameter object.

The final piece to the service is its configuration file. The following code shows the App.config file initially built by Visual Basic for the service class, slightly reformatted to make it easier to read:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.web>
    <compilation debug="true" />
  </system.web>
  <!-- When deploying the service library project, the content of the
       config file must be added to the host's app.config file.
       System.Configuration does not support config files for libraries. -->
  <system.serviceModel>
    <services>
      <service name="QuoteServiceLib.Service1">
        <host>
          <baseAddresses>
            <add baseAddress =
"http://localhost:8732/Design_Time_Addresses/QuoteServiceLib/Service1/" />
          </baseAddresses>
        </host>
        <!-- Service Endpoints -->
        <!-- Unless fully qualified, address is relative to base address
             supplied above -->
<endpoint address ="" binding="wsHttpBinding"
         contract="QuoteServiceLib.IService1">
          <!--
              Upon deployment, the following identity element
              should be removed or replaced to reflect the
              identity under which the deployed service runs.
              If removed, WCF will infer an appropriate identity
              automatically.
          -->
          <identity>
            <dns value="localhost"/>
          </identity>
        </endpoint>
        <!-- Metadata Endpoints -->
        <!-- The Metadata Exchange endpoint is used by the service
             to describe itself to clients. -->
        <!-- This endpoint does not use a secure binding and should
             be secured or removed before deployment -->
        <endpoint address="mex" binding="mexHttpBinding"
         contract="IMetadataExchange"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information,
               set the value below to false and remove the
               metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="True"/>
          <!-- To receive exception details in faults for debugging purposes,
          set the value below to true.  Set to false before deployment
          to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

</configuration>

The <services> element contains service definitions. Each service gives its name and the names of the behaviors it provides. This example defines the service library WcfServiceLibrary1.Service1. The <host> element tells where the service will listen for requests.

The <service> element contains endpoint definitions. These definitions set the addresses, bindings, and contracts for the endpoints. The binding attribute gives the name of the binding that the endpoint uses. This example implements the contract defined by WcfServiceLibrary1 .IService1.

The last endpoint in this example is a Metadata Exchange (MEX) endpoint. It exposes metadata that describes the service to potential clients. A client can use a tool such as SvcUtil to query this endpoint to learn about the service.

The configuration file's <serviceBehaviors> section describes the service's behaviors. In this example, the behavior elements indicate that the service allows clients to look up information about the service and that the service provides details when it has an error.

BUILDING QUOTESERVICE

Modifying the initial service definition to implement the QuoteService isn't too hard. The following code shows the revised interface that defines the service contract. The differences between this version and the initial version are highlighted in bold, so they are easy to see.

<ServiceContract()>
Public Interface IQuoteService

    <OperationContract()>
    Function GetData(ByVal value As Integer) As String

    <OperationContract()>
    Function GetDataUsingDataContract(ByVal composite As CompositeType) _
        As CompositeType

    ' TODO: Add your service operations here
    <OperationContract()>
    Function GetQuote() As Strign

End Interface
                                                  
BUILDING QUOTESERVICE

This example changes the name of the interface to IQuoteService. To change the interface's name to IQuoteService, right-click on the original name, select Rename, enter the new name, and click OK.

The code leaves the initial GetData and GetDataUsingDataContract methods alone and adds a new GetQuote function that takes no parameters and that returns a string.

The following code shows the revised service class that implements this contract. The differences between this version and the initial version are again shown in bold.

Public Class QuoteService
    Implements IQuoteService

    ' Methods GetData and GetDataUsingDataContract omitted.
    ' ...

    ' Return a random quote.
    Public Function GetQuote() As String Implements IQuoteService.GetQuote
        Dim quotes() As String = {
"I stand by all the misstatements that I've made.--Dan Quayle",
            "You can observe a lot just by watching.--Yogi Berra",
            ...
            "Two nations divided by a common language.--Winston Churchill"
        }

        ' Return a random quote.
        Dim rand As New Random
        Return quotes(rand.Next(0, quotes.Length))
    End Function
End Class
                                                  
BUILDING QUOTESERVICE

Again right-click and use Rename to change the service class's name to QuoteService. The GetData and GetDataUsingDataContract are the same as before, so they are not shown here.

This code adds the new GetQuote method. That method simply contains an array of quote strings, picks one randomly, and returns it.

The last change needed to build QuoteService is in the configuration file. The Rename tool updated the App.config file so you only need to change the baseAddress line to the following.

<add baseAddress="http://localhost:8732/Design_Time_Addresses/QuoteServiceLib/
QuoteService/" />

TESTING QUOTESERVICE

After you have built a server, you should test it. Visual Studio provides integrated support for a test service host named WCF Service Host and a test client named WCF Test Client. If you press F5 to run the service library, those programs automatically start so you can test the service.

When you run the program, the WCF Service Host starts and runs the service. Next, the WCF Test Client shown in Figure 38-1 starts. Find the service on the left and expand it to see a list of its behaviors. Double-click a behavior to open it in a tab on the right. In Figure 38-1 the Get Quote behavior is shown on the right.

If the GetQuote method required parameters, they would be listed in the upper grid. You could click a parameter's Value entry and type in a new value.

When you click the Invoke button, the client uses your parameter values to build a request and send it to the service. It displays the results in the lower grid. In Figure 38-1, the GetQuote method returned the quote "You can observe a lot just by watching. — Yogi Berra."

The WCF Test Client lets you test a WCF service.

Figure 38.1. The WCF Test Client lets you test a WCF service.

BUILDING QUOTECLIENT

The client for the QuoteService can be any Windows application. Keeping the service project loaded, open the File menu, expand its Add submenu, and select New Project. In the New Project dialog, select the Windows Forms Application template, name the project QuoteClient, and click OK.

Now, in Solution Explorer, right-click the QuoteClient entry and select Add Service Reference. In the resulting dialog, click the Discover button to find the service, and then click OK to add the reference to the program.

Next, add code to the client application. The example client available for download displays a Get Quote button that executes the following code:

Private Sub btnGetQuote_Click() Handles btnGetQuote.Click
    Me.Cursor = Cursors.WaitCursor

    Dim quote_service As New ServiceReference1.QuoteServiceClient
    lblQuote.Text = quote_service.GetQuote()

    Me.Cursor = Cursors.Default
End Sub
                                                  
BUILDING QUOTECLIENT

This code creates a new ServiceReference1.QuoteServiceClient object, calls its GetQuote method, and displays the result in a label.

When you add the service reference, Visual Studio automatically generates a lot of code including the QuoteServiceClient class. This class includes methods that automatically configure service endpoints and that call the methods exposed by the service.

Right-click the QuoteClient program and make it the startup program. Then press F5 to run the client. When you click the Get Quote button, the program uses the service to display a random quote.

SUMMARY

The idea behind WCF is relatively simple: Allow a client application to call methods provided by a service. Although the idea is simple, WCF is a complicated topic because it provides so much flexibility. It lets clients and services communicate through a variety of transport mechanisms using an assortment of security protocols. WCF provides attributes that make defining service contracts easy, but the great flexibility it provides makes configuring services more difficult.

For more information on WCF, search the Microsoft online help and the Web. A good starting point is the Microsoft WCF home page at msdn.microsoft.com/aa388579.aspx. Several books are also available that cover WCF in depth such as Professional WCF Programming: .NET Development with the Windows Communication Foundation (Klein, Wrox, 2007).

WCF is huge but the .NET Framework is even larger, containing thousands of classes, types, enumerations, interfaces, and other items. To make finding and using all of this material easier, the .NET Framework divides groups of useful files into namespaces. For example, WCF classes are in the System.ServiceModel namespace.

Chapter 40, "Useful Namespaces," describes some other useful namespaces defined by the .NET Framework. It provides a brief overview of some of the most important System namespaces and gives more detailed examples that demonstrate regular expressions, XML, cryptography, reflection, threading, and Direct3D.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.8.147