wcf comprehensive overview

Upload: gaurav-chaurasia

Post on 09-Apr-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/8/2019 WCF Comprehensive Overview

    1/18

    DISTRIBUTED .NET

    Learn The ABCs Of

    Programming WindowsCommunication FoundationAaron Skonnard

    This article is based on a prerelease version of WinFX. All information containedherein is subject to change.

    THIS ARTICLE DISCUSSES:

    The WCF programming model Defining contracts and

    behavior

    Hosting a service and definingendpoints

    Creating and configuringclients

    THIS ARTICLE USES THE FOLLOWING

    TECHNOLOGIES:.NET Framework 2.0, WCF, WSDL, SOAP

    CODE DOWNLOAD AVAILABLE AT:WCF.exe(142 KB)Browse the Code Online

    CONTENTS

    WCF PROGRAMMING MODEL

    SERVICE CONTRACTS AND DISPATCH BEHAVIORDATA CONTRACTS

    MESSAGE AND SERVICE CONTRACTS

    IMPLEMENTING SERVICE CONTRACTS

    HOSTING THE SERVICE AND DEFINING ENDPOINTS

    CHOOSING AND CUSTOMIZING BINDINGS

    OPENING THE HOST

    CONFIGURING SERVICE ENDPOINTS

    USING ACTIVATION SERVICES

    PROGRAMMING CLIENTS

    CONFIGURING CLIENT ENDPOINTS

    GENERATING CLIENT PROXIES

    LOGGING MESSAGES

    CONCLUSIONWindows Communication Foundation (WCF), formerly code-named "Indigo," is

    about to radically change the face of distributed programming for developers

    using the Microsoft .NET Framework. WCF unifies the existing suite of .NET

    distributed technologies into a single programming model that improves the

    overall developer experience through a consistent architecture, new levels of

  • 8/8/2019 WCF Comprehensive Overview

    2/18

    functionality and interoperability, and all the extensibility points you could want.

    This article introduces you to WCF programming and shows you how to get

    started.

    As its name suggests, WCF provides the .NET Framework with a basis for writing

    code to communicate across components, applications, and systems. WCF was

    designed according to the tenets of service orientation. A service is a piece of

    code you interact with through messages. Services are passive. They wait forincoming messages before doing any work. Clients are the initiators. Clients send

    messages to services to request work.

    Figure 1 Services and Endpoints

    Services expose one or more endpoints where messages can be sent. Each

    endpoint consists of an address, a binding, and a contract (see Figure 1). The

    address specifies where to send messages. The binding describes how to send

    messages. And the contract describes what the messages contain. Clients need to

    know this information before they can access a service.

    Services can package up endpoint descriptions to share with clients, typically by

    using Web Services Description Language (WSDL). Then clients can use the

    provided service description to generate code within their environment capable of

    sending and receiving the proper messages (see Figure 2).

    Figure 2 Sharing Endpoint DescriptionsWindows Communication Foundation provides a new library of classes found in

    the System.ServiceModel namespace that bring these service-oriented concepts

    to life. This is what's typically referred to as the WCF programming model.

    WCF Programming ModelWith WCF, you're either writing services that expose endpoints or you're writing

    clients that interact with endpoints. Hence, endpoints are central to the WCF

    programming model and infrastructure. WCF models endpoints with the .NET

    classes and interfaces shown in Figure 3. This mapping is true whether you're

    writing WCF clients or services.Figure 3 WCF Classes and Interfaces

    Element Class or Interface

  • 8/8/2019 WCF Comprehensive Overview

    3/18

    Endpoint System.ServiceModel.ServiceEndpoint

    Address System.Uri

    Binding System.ServiceModel.Binding

    Contract Interfaces annotated with System.ServiceModel attributes

    When building a WCF service, you typically start by defining a .NET interface

    definition to serve as the service contract. Then you implement the service

    contract in a .NET class, known as the service type, and configure its behavior.

    Next, you define the endpoints the service will expose, specifying the address,

    binding, and contract for each one. Finally, you host the service type in an

    application using the WCF hosting infrastructure. Once the service type is hosted,

    clients can retrieve its endpoint descriptions and begin integrating with it.

    When building a WCF client, you first need the description of the target endpoint

    you want to access. The endpoint description can be used to dynamically create a

    typed proxy. WCF provides a tool named SvcUtil.exe for automating this process.

    Then you can write code against the typed proxy to access the service by sending

    the appropriate messages to the target endpoint.

    Service Contracts and Dispatch BehaviorYou model service contracts in .NET using traditional C# interface definitions. Youcan use any .NET interface as a starting point, such as the one shown here:

    namespace ServiceLibrary

    {

    public interface IEchoService

    {

    string Echo(string msg);

    }

    }

    To make this a WCF service contract, you must annotate the interface itself with

    [ServiceContract] and each operation you want to expose with[OperationContract]:

    using System.ServiceModel;

    namespace ServiceLibrary

    {

    [ServiceContract(Namespace="http://example.org/echo/")]

    public interface IEchoService

    {

    [OperationContract]

    string Echo(string msg);

    }

    }

    These attributes influence the mapping between the worlds of .NET and SOAP.

    WCF uses the information found in the service contract to perform dispatching

    and serialization. Dispatching is the process of deciding which method to call for

    an incoming SOAP message. Serialization is the process of mapping between the

    data found in a SOAP message and the corresponding .NET objects used in the

    method invocation. This mapping is controlled by an operation's data contract.

    WCF dispatches based on the message action. Each method in a service contract

  • 8/8/2019 WCF Comprehensive Overview

    4/18

    is automatically assigned an action value based on the service namespace and

    method name. For example, the default action for the Echo method just shown is

    http://example.org/echo/Echo. You can customize the action value for each

    method using [OperationContract]. A value of * can be used for any action when

    a specific match doesn't exist.

    In the following example, WCF will dispatch messages with an action of

    urn:echo:string to the Echo method. Messages with any other action aredispatched to the EchoMessage method:

    [ServiceContract(Namespace="http://example.org/echo/")]

    public interface IEchoService

    {

    [OperationContract(Action="urn:echo:string")]

    string Echo(string msg);

    [OperationContract(Action="*")]

    Message EchoMessage(Message msg);

    }

    Data ContractsOnce the target method has been determined based on the action, WCF relies on

    the method's data contract to perform serialization. The data contract is defined

    by the types used in the method signature. In the previous example,

    EchoMessage is generic and could be used to process a variety of incoming SOAP

    messages. Therefore I've used Message to model the input and output. Message

    is a special type used to represent all messages flowing through WCF. When

    using Message, WCF does not perform type-based serialization. Instead, it just

    gives you direct access to what's found in the SOAP message.

    When Message is not used, WCF performs serialization to map between the data

    found in the SOAP message and the corresponding .NET objects needed to invoke

    the method. For example, in the case of Echo, WCF maps the SOAP payload to a.NET string. WCF provides an implicit mapping for all .NET primitive types (string,

    int, double, and so on).

    The way WCF serializes .NET classes depends on the serialization engine in use.

    The default serialization engine is known as DataContract, a simplified version of

    XmlSerializer, the default serialization engine used in ASMX today. DataContract

    defines attributes for annotating class definitions to influence the serialization

    process. Here's an example of it in use:

    [DataContract(Namespace="http://example.org/person")]

    public class Person

    {

    [DataMember(Name="first", Order=0)]public string First;

    [DataMember(Name="last", Order=1)]

    public string Last;

    [DataMember(IsRequired=false, Order=2)]

    private string id;

    ...

    }

    With DataContract, only fields marked with DataMember will be serialized. And

  • 8/8/2019 WCF Comprehensive Overview

    5/18

    you can serialize private fields. This is much different from the way XmlSerializer

    works. Now you can use Person in an operation contract:

    [ServiceContract(Namespace="http://example.org/echo/")]

    public interface IEchoService

    {... // previous methods omitted

    [OperationContract]

    Person EchoPerson(Person p);

    }

    When EchoPerson is invoked, WCF will serialize Person instances according to the

    DataContract attributes specified on the Person class. DataContract produces a

    very simple XML structurea sequence of elements. You can control the name of

    each element, the order, and whether a particular element is required, but that's

    about it.

    If you need to do anything more sophisticated, WCF lets you fall back to using

    XmlSerializer. You indicate your desire to use XmlSerializer by annotating the

    interface with [XmlSerializerFormat]:

    [ServiceContract]

    [XmlSerializerFormat]

    public interface IEchoService { ... }

    This tells WCF to use XmlSerializer for all types in the contract, according to the

    XmlSerializer defaults and the various System.Xml.Serialization customization

    attributes. This makes it much easier to move existing ASMX services forward to

    WCF.

    WCF also supports serializing types marked with [Serializable], which allows .NET

    remoting types to work with WCF without change. WCF provides an implicit

    mapping for [Serializable] types where all public/private fields are automaticallyserialized.

    Message and Service ContractsAll of the examples up to this point have relied on WCF to automatically map the

    method signature to the SOAP message. The parameter list and return type are

    always mapped to the SOAP body for the request and response, respectively. If

    you need to support headers, you can write another class that models the

    structure of the entire SOAP envelope for the particular operation, specifying

    which fields map to headers versus the body. You define this mapping with the

    [MessageContract] attributes:

    [MessageContract]public class EchoPersonMessage

    {

    [MessageBody]

    public Person Person;

    [MessageHeader]

    public Authorization Authorization;

    }

    In this example, the Person field is mapped to the SOAP body while the

  • 8/8/2019 WCF Comprehensive Overview

    6/18

    Authorization field is mapped to a SOAP header. Now you can use

    EchoPersonMessage in an operation contract:

    [ServiceContract]

    public interface IEchoService

    {... // previous methods omitted

    [OperationContract]

    void EchoPerson(EchoPersonMessage msg);

    }

    Using MessageContract is a more advanced technique that is only necessary

    when you need direct control over the SOAP contract.

    Implementing Service ContractsNow you can implement the service contract by simply implementing the .NET

    interface in a class:

    using System.ServiceModel;

    namespace ServiceLibrary

    {

    public class EchoService : IEchoService

    {

    public string Echo(string msg)

    {

    return msg;

    }

    ... // remaining methods omitted

    }

    }By doing this, EchoService is guaranteed to support the service contract defined

    by IEchoService. When using an interface to define the service contract, you

    don't need any contract-related attributes on the class definition. However, you

    may want to use [ServiceBehavior] to influence its local behavior:

    using System.ServiceModel;

    namespace ServiceLibrary

    {

    ... // interface definition omitted

    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single,

    ConcurrencyMode=ConcurrencyMode.Multiple)]

    public class EchoService : IEchoService

    {

    ...

    This particular example tells WCF to manage a singleton instance of the service

    type and to allow multithreaded access to the instance. There is also an

    [OperationBehavior] attribute for controlling operation-level behavior.

  • 8/8/2019 WCF Comprehensive Overview

    7/18

    Behaviors influence processing within the host, but have no impact on the service

    contract whatsoever. Behaviors are one of the primary WCF extensibility points.

    Any class that implements IServiceBehavior can be applied to a service through

    the use of a custom attribute or configuration element.

    Hosting the Service and Defining Endpoints

    To use EchoService, you need to host it in a .NET-based application. TheServiceHost class gives you direct control over the WCF hosting infrastructure.

    You instantiate ServiceHost based on a particular service type. The following code

    shows how to do this in a console application:

    using System;

    using System.ServiceModel;

    using ServiceLibrary;

    class Program

    {

    static void Main(string[] args)

    {

    using (ServiceHost host = new ServiceHost(

    typeof(EchoService), new Uri("http://localhost:808

    0/echo")))

    {

    ...

    In addition to specifying the service type, you also specify the base addresses for

    the different transports you plan to use. In this example, I've specified a base

    address of http://localhost:8080/echo. This will be used as the base for any

    relative HTTP addresses I might specify when adding endpoints. The base HTTP

    address is also used as the default for retrieving the service description.

    You then add the service endpoints. Again, a service may have one or more

    endpoints and each endpoint consists of an address, a binding, and a contract.You provide this information to your ServiceHost by calling AddServiceEndpoint.

    This is where you specify the service contract you defined earlier (IEchoService).

    For the binding, you typically choose from one of the many predefined bindings

    that ship with WCF and an appropriate address given the binding's transport.

    Here's an example:

    host.AddServiceEndpoint(typeof(IEchoService),

    new BasicHttpBinding(), "svc");

    host.AddServiceEndpoint(typeof(IEchoService),

    new NetTcpBinding(), "net.tcp://localhost:8081/echo/svc");

    In this particular example, I've specified IEchoService as the contract for both

    endpoints, but with each endpoint using a different binding and address. The firstendpoint uses the BasicHttpBinding and a relative HTTP address of svc (which

    would make its absolute address http://localhost:8080/echo/svc). The second

    endpoint uses the NetTcpBinding and an address of

    net.tcp://localhost:8081/echo/svc. Therefore, this service allows consumers to

    communicate with it over either HTTP or TCP using different WS-* protocols, as

    defined by each binding.

    Choosing and Customizing Bindings

  • 8/8/2019 WCF Comprehensive Overview

    8/18

    The WCF infrastructure relies heavily on endpoint definitions to control how

    messages are processed. In fact, WCF uses the endpoint definitions to

    dynamically build the appropriate message processing runtime within hosts and

    clients. The binding has the most significant influence on this process.

    The binding controls three aspects of message communication: the suite of WS-*

    protocols, including WS-Security, WS-ReliableMessaging, and so on; the message

    encoding, such as XML 1.0, Message Transmission Optimization Mechanism(MTOM), and binary; and the transport protocol, including HTTP, TCP, and

    Microsoft Message Queuing (MSMQ). A given binding specifies one message

    encoding and one transport, but it can specify numerous WS-* protocols. Given

    that, there are an overwhelming number of permutations that could be used. To

    simplify things, WCF provides a set of predefined bindings that fit the most

    common use cases. Figure 4 lists some of these and describes what they

    embody.Figure 4 Predefined WCF Bindings

    Class Name Element Name Transport Encoding WS-*Protocols

    BasicHttpBinding basicHttpBinding HTTP XML 1.0 WS-I Basic

    Profile 1.1

    WSHttpBinding wsHttpBinding HTTP XML 1.0 Messagesecurity,reliablesessions,andtransactions

    WSDualHttpBinding wsDualHttpBinding HTTP XML 1.0 Messagesecurity,reliablesessions,andtransactions

    NetTcpBinding netTcpBinding TCP Binary Transportsecurity,reliablesessions,andtransactions

    NetNamedPipeBinding netNamedPipeBinding NamedPipes

    Binary Transportsecurity,reliablesessions,andtransactions

    NetMsmqBinding netMsmqBinding MSMQ Binary Transportsecurityand queuetransactions

    Developers who care primarily about interoperability and don't need WS-*

    functionality will typically use BasicHttpBinding. Developers who care about

    interoperability, but also need message-based security, reliable messaging, and

    transactions will typically choose WSHttpBinding. Developers using WCF on both

    sides (client and service) can choose from NetTcpBinding and

  • 8/8/2019 WCF Comprehensive Overview

    9/18

    NetNamedPipeBinding, which provide significant optimizations. Those building

    asynchronous systems can choose NetMsmqBinding. There are also a few

    bindings that aren't listed here, such as MsmqIntegrationBinding for integrating

    with existing MSMQ applications, NetPeerTcpBinding for building peer-to-peer

    services, and WSFederationBinding for federated security. A service can support

    any combination of these bindings.

    Once you choose a binding and instantiate it, you can customize some of itscharacteristics through the properties exposed on the binding class. The following

    example shows how to enable transport-based security on the BasicHttpBinding:

    BasicHttpBinding b = new BasicHttpBinding();

    b.Security.Mode = BasicHttpSecurityMode.Transport;

    b.Security.Transport.ClientCredentialType =

    HttpClientCredentialType.Basic;

    host.AddServiceEndpoint(typeof(IEchoService), b, "svc");

    If the predefined bindings and their customizations still don't fit your needs, you

    can also write a custom binding by implementing a class that derives from

    Binding.

    Opening the HostNow that you've configured the host with endpoint information, WCF can build

    the runtime needed to support your configuration. This occurs when you call

    Open on a particular ServiceHost:

    host.Open();

    Once the call to Open returns, the WCF runtime is built and ready to receive

    messages at the addresses specified by each endpoint. During this process, WCF

    generates an endpoint listener for each supplied endpoint and the code needed to

    support the WS-* protocols specified by the binding. (An endpoint listener is the

    piece of code that actually listens for incoming messages using the specifiedtransport and address.)

    You can retrieve information about the service at run time through the object

    model exposed by ServiceHost. This allows you to retrieve anything you might

    want to know about the initialized service, such as what endpoints it exposes and

    what endpoint listeners are currently active.

    Figure 5 shows a complete example of the console application that hosts

    EchoService. Figure 6 shows the output. Notice there are two additional endpoint

    listener addresses that I didn't specify in a ServiceEndpoint. WCF automatically

    provided these using the base HTTP address for retrieving the service description.Figure 5 Console App Hosting EchoService

    class Program{

    static void Main(string[] args)

    {

    using (ServiceHost host = new ServiceHost(

    typeof(EchoService), new Uri("http://localhost:808

    0/echo")))

    {

    // define the service endpoints

    host.AddServiceEndpoint(typeof(IEchoService),

  • 8/8/2019 WCF Comprehensive Overview

    10/18

    new BasicHttpBinding(), "svc");

    host.AddServiceEndpoint(typeof(IEchoService),

    new NetTcpBinding(), "net.tcp://localhost:8081

    /echo/svc");

    host.Open();

    Console.WriteLine(

    "{0} is open and has the following endpoints:\

    n",

    host.Description.ServiceType);

    int i=1;

    foreach (ServiceEndpoint end in host.Description.E

    ndpoints)

    {

    Console.WriteLine("Endpoint #{0}", i++);

    Console.WriteLine("Address: {0}",

    end.Address.Uri.AbsoluteUri);

    Console.WriteLine("Binding: {0}",

    end.Binding.Name);

    Console.WriteLine("Contract: {0}\n",end.Contract.Name);

    }

    Console.WriteLine(

    "The following EndpointListeners are active:\n

    ");

    foreach (EndpointListener l in host.EndpointListen

    ers)

    Console.WriteLine(l.Listener.Uri.AbsoluteUri);

    // keep the process alive

    Console.ReadLine();

    }

    }

    }

    Figure 6 Output of Console AppIf you browse to http://localhost:8080/echo, you'll see the default WCF help page

    (see Figure 7) and if you browse to http://localhost:8080/echo?wsdl, you'll see

    the generated WSDL definition. The other endpoint listener

    (http://localhost:8080/echo/mex) knows how to speak WS-MetadataExchange.

    It's important to note that this sample is not using IIS in any way. WCF provides

    built-in integration with httpsys, which allows any application to automatically

  • 8/8/2019 WCF Comprehensive Overview

    11/18

    become an HTTP listener.

    Figure 7 EchoService Help Page

    Configuring Service EndpointsHardcoding endpoint information into the host application is not ideal since

    endpoint details may change over time. It's not hard to imagine how you could

    store the endpoint information in a configuration file or database and read it whileinitializing ServiceHost. Since this is a common need, WCF automatically provides

    this functionality through the predefined configuration

    section.

    The following configuration file defines the same two endpoints that were

    specified by calling AddServiceEndpoint:

    If you add this configuration file to the host application shown in Figure 5 and

  • 8/8/2019 WCF Comprehensive Overview

    12/18

    comment out the calls to AddServiceEndpoint, you'll see the same results in the

    output. This increases deployment flexibility since the communication details are

    completely factored out of the compiled code. You can also configure bindings

    within . Figure 8 shows how to configure

    basicHttpBinding to use transport security like I had done in code.Figure 8 Configuring Transport Security

    ...

    You can even define new custom bindings from scratch using the

    element, which would be equivalent to deriving a new class

    from Binding. When it comes to configuring endpoints, bindings, and evenbehaviors, anything you can do in code, you can also do through configuration.

    Figure 9 Using the GUI to Define an EndpointAlthough IntelliSense for the configuration file works well in Visual Studio

    2005, some developers still prefer to avoid XML altogether. The WinFX SDK

    includes a tool called SvcConfigEditor, which provides a graphical interface for

    working with the various settings. Figure 9 shows how

    to configure endpoints using this tool.

  • 8/8/2019 WCF Comprehensive Overview

    13/18

    Using Activation ServicesAlthough I've been experimenting with console applications, ServiceHost makes it

    easy to host WCF services in a variety of applications, including Windows Forms

    applications and managed Windows Services. In all of these application scenarios,

    you're responsible for managing the process hosting WCF. This is known as self-

    hosting in WCF terms.In addition to self-hosting, WCF also makes it possible to activate services by

    using IIS along with traditional Web hosting techniques. You can accomplish this

    by using a .svc file (similar to .asmx) that specifies the service type to host:

    You place this file in a virtual directory and deploy your service type to its \bin

    directory or the Global Assembly Cache (GAC). When using this technique you

    specify the service endpoint in the web.config, but you don't need to specify the

    address since it's implied by the location of the .svc file.

    ...

    Now if you browse to the .svc file, you'll notice the help page is displayed,

    showing that a ServiceHost was automatically created within an ASP.NET

    application domain. This is accomplished by an HTTP module that filters incoming

    .svc requests and automatically builds and opens the appropriate ServiceHost

    when needed.If you install the WinFX extensions for Visual Studio 2005, you'll find a new Web

    Site project template called Indigo Service (this name will change). When you

    create a new Web site based on this template, it automatically gives you the .svc

    file along with the corresponding implementation class (found in App_Code). It

    also comes with a default endpoint configuration in web.config.

    On IIS versions 5.1 and 6.0 the WCF activation model is tied to the ASP.NET

    pipeline, and therefore to HTTP. IIS 7.0, which is planned for release with

    Windows Vista, introduces a transport-neutral activation mechanism known as

    Windows Activation Services (WAS). With WAS, you'll be able to leverage .svc-

    like activation over any transport.

    Programming Clients

    Programming WCF clients involves sending messages to a service endpointaccording to its address, binding, and contract. To accomplish this, you first

    create a ServiceEndpoint representing the target endpoint. The following example

    shows how to create a ServiceEndpoint, based on the service's HTTP endpoint, in

    a client console application:

    using System;

    using System.ServiceModel;

  • 8/8/2019 WCF Comprehensive Overview

    14/18

    using ServiceLibrary;

    class Program

    {

    static void Main(string[] args)

    {

    ServiceEndpoint httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IEchoServic

    e)),

    new BasicHttpBinding(), new EndpointAddress(

    "http://localhost:8080/echo/svc");

    This code assumes that the client has access to the same IEchoService interface

    definition that the service used and that the client knows what binding and

    address to use. Then you can create a ChannelFactory based on the

    ServiceEndpoint:

    ChannelFactory factory =

    new ChannelFactory(httpEndpoint);

    ChannelFactory creates typed proxies. In this case, it creates proxies of typeIEchoService, which you can use to invoke the operations defined by the

    contract:

    IEchoService svc = factory.CreateChannel();

    Console.WriteLine(svc.Echo("Hello, world"));

    If the service requires a customized binding, you will need to create the binding

    and customize it before creating ServiceEndpoint. If you want to access the TCP

    endpoint, simply create another ServiceEndpoint specifying the TCP endpoint

    details and supply it to ChannelFactory instead of the HTTP endpoint. Everything

    else would work the same.

    The proxy shields you from the different addresses and bindings in use, allowingyou to write application code against the service contract. Figure 10 shows the

    complete client console application.Figure 10 EchoService Client App

    using System;

    using System.ServiceModel;

    using ServiceLibrary;

    class Program

    {

    static void Main(string[] args)

    {

    try{

    // define service endpoints on client

    ServiceEndpoint httpEndpoint = new ServiceEndpoint

    (

    ContractDescription.GetContract(

    typeof(IEchoService)),new BasicHttpBinding(

    ),

    new EndpointAddress("http://localhost:8080/ech

  • 8/8/2019 WCF Comprehensive Overview

    15/18

    o/svc"));

    ServiceEndpoint tcpEndpoint= new ServiceEndpoint(

    ContractDescription.GetContract(

    typeof(IEchoService)),

    new NetTcpBinding(), new EndpointAddress(

    "net.tcp://localhost:8081/echo/svc"));

    IEchoService svc = null;

    // create channel factory based on HTTP endpoint

    using (ChannelFactory httpFactory =

    new ChannelFactory(httpEndpoint)

    )

    {

    // create channel proxy for endpoint

    svc = httpFactory.CreateChannel();

    // invoke service operation

    Console.WriteLine("Invoking HTTP endpoint: {0}

    ",

    svc.Echo("Hello, world"));}

    // create channel factory based on TCP endpoint

    using (ChannelFactory tcpFactory =

    new ChannelFactory(tcpEndpoint))

    {

    // create channel proxy for endpoint

    svc = tcpFactory.CreateChannel();

    // invoke service operation

    Console.WriteLine("Invoking TCP endpoint: {0}"

    ,

    svc.Echo("Hello, world"));

    }

    }

    catch (Exception e)

    {

    Console.WriteLine(e);

    }

    }

    }

    Configuring Client EndpointsHardcoding endpoint information into client code is also less than ideal. So WCF

    provides a similar configuration mechanism for specifying client endpoints within

    . The following application configuration file specifies the

    same client endpoint details used in the code:

  • 8/8/2019 WCF Comprehensive Overview

    16/18

    Notice that I've given each client endpoint a name. You can use this name in your

    code when creating a ChannelFactory, as illustrated in the following code:

    using (ChannelFactory httpFactory =

    new ChannelFactory("httpEndpoint"))

    {

    svc = httpFactory.CreateChannel();

    Console.WriteLine("Invoking HTTP endpoint: {0}",

    svc.Echo("Hello, world"));

    }

    Now when you want to create a ChannelFactory for the TCP endpoint, you can

    simply change the configuration name to tcpEndpoint. You can also configurebindings in the client configuration file just like I did in the service configuration

    file.

    If you add this configuration file to the client console application shown in Figure

    10, comment out the code to create the ServiceEndpoint objects, and specify the

    endpoint names when constructing each ChannelFactory, the result will be the

    same.

    Generating Client ProxiesThe preceding examples assumed the client had access to the same interface

    definition used to implement the service. This is common when .NET is used to

    implement both sides (in traditional .NET remoting scenarios), but that's not

    always the case, and it's never the case when the service wasn't implementedwith the .NET Framework. The preceding examples also assumed the client knew

    the precise endpoint details in advance, which isn't always common either.

    When clients don't have access to such information, they can discover it using the

    WS-MetadataExchange specification. Services share endpoint descriptions with

    clients through WSDL definitions. Most service platforms provide tools for

    generating client-side code from WSDL definitions. The WinFX SDK provides

    SvcUtil.exe for this purpose.

    When executing SvcUtil.exe, you specify the URL of the WSDL definition and it

    will generate the necessary .NET code and configuration elements that define the

    endpoints and bindings used by the service endpoints. Figure 11 shows the

    output of running SvcUtil.exe against http://localhost:8080/echo. Notice that it

    generates two files: EchoService.cs and output.config.

    Figure 11 SvcUtil.exe Output

  • 8/8/2019 WCF Comprehensive Overview

    17/18

    EchoService.cs contains a .NET interface definition equivalent to the one the

    service implemented. Output.config contains the client endpoint information

    needed to access the service (similar to what I just wrote manually). You'll need

    to merge the contents of output.config with your application configuration file

    manually. With this in place, you can write client code using the same techniques

    shown in the previous examples, only using the generated interface and

    configuration file.In general, the WCF client programming model is explicit about the service

    boundary. You create a typed channel against a specific service endpoint and

    then send messages through it. Although this helps emphasize the tenets of

    service orientation, it can be tedious to work at this level all the time. To help

    you, SvcUtil.exe also generates a proxy class that completely hides the

    ChannelFactory and ServiceEndpoint creation details. If you open EchoService.cs,

    you'll find the following class definition:

    public partial class EchoServiceProxy :

    System.ServiceModel.ClientBase, IEchoService

    {

    public EchoServiceProxy(){

    }

    public EchoServiceProxy(string endpointConfigurationName)

    :

    base(endpointConfigurationName)

    {

    }

    ...

    This proxy class can simplify your client application code. All you have to do is

    instantiate the proxy, specify the name of the endpoint configuration, and make

    method calls. Here's an example:

    using (EchoServiceProxy proxy = new EchoServiceProxy("IEchoSer

    vice"))

    {

    // invoke service operation

    Console.WriteLine("Invoking HTTP endpoint: {0}",

    proxy.Echo("Hello, world"));

    }

    using (EchoServiceProxy proxy = new EchoServiceProxy("IEchoSer

    vice1"))

    {

    // invoke service operation

    Console.WriteLine("Invoking TCP endpoint: {0}",proxy.Echo("Hello, world"));

    }

    The generated configuration file (output.config) defines the IEchoService and

    IEchoService1 endpoint configurations.

    Logging MessagesAs you begin working with the WCF programming model, you may find it useful to

    trace the SOAP messages traveling between clients and services. Windows

  • 8/8/2019 WCF Comprehensive Overview

    18/18

    Communication Foundation provides built-in support for message logging, which

    can be turned on through your application configuration file.

    Figure 12 SvcTraceViewer.exeSvcConfigEditor provides a Diagnostics tab where you can enable the messaging

    logging features. Once you enable messaging logging and rerun the app, you'll

    see the trace file appear in the specified location. The WinFX SDK also provides

    SvcTraceViewer.exe for viewing the information in a trace file (see Figure 12).

    ConclusionWCF is a new step in distributed programming for developers using the .NET

    Framework. If you currently build systems using any of today's .NET distributed

    technologies, it's time to start paying attention to WCF and the future it holds.

    It's only a matter of time before all .NET-targeted code related to

    communications will be written using WCF.

    Note that all of the code samples shown in this article are based on Visual Studio2005 and the WCF November 2005 CTP.

    Aaron Skonnard is a co-founder ofPluralsight, a Microsoft .NET training

    provider. Aaron is the author ofPluralsight's Applied Web Services 2.0, Applied

    BizTalk Server 2006, and Introducing WCF courses. Aaron has spent years

    developing courses, speaking at conferences, and teaching professional

    developers. Reachhim at pluralsight.com/aaron.