What's a Service Contract in WCF?

It's important to first understand what defines a service contract. Basically a service contract defines the group of operations in a service, the operation's signatures and message datatypes. It also defines the location of the operations and the specific protocols and serialization formats that support communication with the service.

In WCF, we define a service contracts with method and class attributes. The following is a simple service with it's associated attributes:

// Step 1 Import the necessary namespace
using System;
using System.ServiceModel;

namespace myHoakyService
{
   //Step 2 Use the ServiceContract attribute to 
//
identify a class or interface that defines a
//WCF service contract for clients.
[ServiceContract(Namespace=
http://localhost/HoakyService)]
public interface IHoakyService
{
       //Step 3 Identify Service Operations 
//with the OperationContract
//attribute and expose it to clients
[OperationContract]
string HoakyMethod();
       //Note: You can even include methods 
//that are not exposed to clients.
string HoakyNonAccessibleMethod();
}
  //Note: You can even apply the ServiceContract to classes
[ServiceContract(Namespace=
http://locahost/HoakyClassService)]
public class HoakyClassService
{
     [OperationContract]
string HoakyClassMethod()
{
return "This is a hoaky method.";
}
}
//Step 4 Design a class that implements the ServiceContract Interface
public class HoakyClass : IHoakyService
{
public string HoakyMethod()
{
return HoakyNonAccessibleMethod();
}
    string HoakyNonAccessibleMethod()
{
return "This is a hoaky method.";
}
}
}

Microsoft's recommendation is to restrict your Service Contracts to interfaces because it defines the group of operations and
 the operation signatures. Let's read between the lines here. A group of operations is basically the interface's methods, and the operation signatures are well the method signatures. Nothing difficult about that now is there?

The other benefits of using interfaces for Service Contracts are that they can be extended by other interfaces.
 You can also create classes that implement multiple service contract interfaces whereas a class can only implement one service contract. Versioning becomes easier because old clients can still point to the old service contract interface while newer clients can point to a newer service contract interface.

Pass By Value

You're parameters and return values represent the method signatures or operation signatures. The biggest thing to understand with WCF is that everything is pass by value or as I like to say "pass by copy". This is actually standard in many interoperable applications.
The next biggest thing to remember is that both parameters and return values must be serializable(convert to XML). Windows Communication Foundation (WCF) uses the DataContractSerializer as its default serialization engine to convert data into XML and to convert XML back into data.
The following datatypes are handled by the DataContractSerializer:

  • Primitive types such as integers and strings
  • Simple composite types such as DateTime
  • XML-based types such as XmlElement
  • Collections
  • Enumerations
  • Types marked with the SerializableAttribute attribute

For more information see:  Types Supported by the Data Contract Serializer  

 Note to VB programmers: The value of the parameter names in the operation signature are part of the contract and are case sensitive.

It is possible to change the exposed name of your return values and parameters. You would use the MessageParameterAttribute attribute as follows:

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.Text;
namespace MyHoakierService
{
  [ServiceContract(Namespace="http://localhost/HoakierService")]
  public interface IHoakierService{
    [OperationContract]
    [return:MessageParameter(Name = "HoakyOut")]
    string HoakyMethod([MessageParameter(Name = "HoakyIn")]string input);
  }

On to Data Contracts

Wait, we had service contracts and now we have data contracts? Well we just mentioned that WCF methods work on a Pass By Value or "pass by copy" method. Why do we need data contracts? Ok, data contracts make an operation more widely accessible by a variety of clients. In other words, it's more interoperable.

We implement data contracts by simply marking our types with DataContractAttribute and DataMemberAttribute attributes. Data contracts are opt-in contracts. You have to apply the data contract attribute for them to be serialized.

using System;
using System.Runtime.Serialization;
namespace myHoakyService
{
[DataContract]
public class Hoakster
{
    // Step 1: Serialize a memeber.
    [DataMember]
    internal string HoakyName;
    // Step 2: Serialize a private member.
    [DataMember]
    private int HoakyNumber;
    // Note: No DataMemberAttribute = No seralized data.
    private string HoakyNonSerialized;
    // Note: Not serialized
    private string HoakyNonSerializedValue;
    //Step 3: serializing a Property that accesses a non-serialized member.
    [DataMember]
    public string HoakySeralizedValue
    {
        get { return HoakyNonSerializedValue;}
        set { HoakyNonSerializedValue = value; }
    }
}
}

Be aware, you're not limited to using Datacontract attributes and primitives. You can use other serialization methods as explained here: Specifying Data Transfer in Service Contracts  (Some interesting stuff in there about Message Contracts which I'll cover in another post.)

Message Exchange Patterns


Service operations are supported by a SOAP message exchange that transfers application data back and forth,
including the data required to support standard security,
transaction, and session-related features.
This being the case, the service operation signature dictates a certain underlying message exchange pattern (MEP)
that can support the data transfer and the features an operation requires. Note that now an operation signature is building up to include security, transaction, and session data.

There are three patterns in the WCF programming model that you can use.
The request/reply is just like it sounds. A client sends a request with parameters and waits for the server to reply with a return value. Note that the return message/value could be an empty message as a result of a void return on an operation.
Another return type would be a Soap FaultException that notifies the client of an error.

A one-way operation is one in which a client invokes an operation and continues processing after WCF writes the message to the network. Note that the client wouldn't be processing any FaultException errors returned to it. To designate an operation as one-way apply the OperationContractAttribute with a IsOneWay=true property.

[OperationContractAttribute(IsOneWay=true)]
void hoakyMethod(string HoakyInput);

A duplex pattern allows the service and the client to send messages to each other independently whether using one-way or request/reply messaging. This works well for asynchronous operations or services that have to notify a client with a message. When you design a duplex contract, you  design two interfaces; one interface to send messages from client to service and a callback interface to send messages from the service to the client.

You start by declaring your ServiceContract on your receiver interface (the one that the client sends the messages to). You add a CallBackContract property that points to the callback interface.  And yes, this implementation tells the client "Hi Hoaky Client".

//Step 1: Define your ServiceContract for the receiving interface.
[ServiceContract(Namespace = http://localhost/MyHoakyDuplexService,
SessionMode=SessionMode.Required,
                 CallbackContract=typeof(IHoakyCallback))]
public interface IHoaky
{
    [OperationContract(IsOneWay=true)]
    void Hoaky();   
}
// Step 2: Create a callback interface so the service can say something to the client.
// This defines the methods that the service can call on the client. So yes, if your client
// needs to hear from the service, it must implement this interface.
public interface IHoakyCallback
{
   //Note: We're still using the OperationContract attribute.
   //This time we're using the OneWay
   //property so the operation can talk in a one way direction.
    [OperationContract(IsOneWay = true)]
    void HoakyCaller(string hoakified);
}
//Step 3: Create a Class that implements the Service Contract Interface
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class HoakyService : IHoaky
{
    string hoakified;
    IHoakyCallback callback = null;
    public HoakyService()
    {
        hoakified= "Hi Hoaky Client";
        //Note: The following allows the service to call a method on the client.
        callback = OperationContext.Current.GetCallbackChannel<IHoakyCallback>();
    }
    public void Hoaky()
    {
        callback.HoakyCaller(hoakified);        
    }
}

Security

You have 2 choices. You can set the secuirty of your message in the binding of the endpoint or you can turn off the message security in the binding. In most cases your system level settings will take care of what you need. Only in special circumstances would you set specific message protecting in the binding of an endpoint for specific messages.

There are more topics to cover but I think I'll leave those topics to another post.

Print | posted on Wednesday, December 03, 2008 8:04 AM

Feedback

No comments posted yet.

Your comment:





 
Please add 8 and 4 and type the answer here:

Copyright © Desirea Herrera

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski