Programming With WCF


Programming WCF clients and services you will see many concepts that are known from other technologies. Nothing is really new, but all the different programming models are combined that you just have to learn one model instead of multiple when using different communication techniques.

Next, we look into:

  • Contracts

  • Service Implementation

  • Binding

  • Hosting

  • Clients

Contracts

A contract defines what functionality a service offers and what functionality can be used by the client. The contract can be completely independent of the implementation of the service.

The contract of Web services is the WSDL document. Developing Web services with ASP.NET, the contract doesn't have the big role as it should have. With ASP.NET contracts are done implicitly by specifying attributes with the Web service methods. Of course you can also use a tool such as WSCF from Thinktecture (http://www.thinktecture.com) to explicitly design a contract.

WCF has a greater focus on designing contracts. The contracts defined by WCF can be grouped into three different contract types: service contracts, data contracts, and message contracts. The contracts can be specified (this is similar to ASP.NET) by using .NET attributes.

  • Service contract: The service contract is used to define the WSDL that describes the service. This contract is defined with interfaces or classes.

  • Data contract: The data contract defines the data received and returned from the service. The classes used for sending and receiving messages have data contract attributes associated.

  • Message contract: If complete control over the SOAP message is needed, a message contract can specify what data should go into the SOAP header, and what belongs to the SOAP body.

WSDL was discussed in Chapter 28, "Web Services."

Let's get into contracts in more detail.

Service contract

The service contract defines the operations the service can perform. The attribute [ServiceContract] is used with interfaces or classes to define a service contract. The methods that are offered by the service have the attribute [OperationContract] applied as you can see with the ICourseRegistration service.

 [ServiceContract] public interface ICourseRegistration { [OperationContract] public bool RegisterForCourse(Course course, Attendee attendee); } 

With the service contract, you can also define the requirements that the service has from the transport with the attribute [BindingRequirements]. The property RequireOrderedDelivery defines that the messages sent must arrive in the same order. With the property QueuedDeliveryRequirements you can define that the message is sent in a disconnected mode, e.g. by using Message queuing. With the property TransactionFlowRequirements you can define transactional requirements as known from Enterprise Services.

Data contract

With the data contract, CLR types are mapped to XML schemas.

The data contract is different from other serialization mechanisms; with runtime serialization, all fields are serialized (including private fields), with XML serialization only the public fields and properties are serialized. The data contract requires explicit marking of the fields that should be serialized with the[DataMember] attribute. This attribute can be used no matter if the field is private or public.

 [DataContract(Namespace="http://www.thinktecture.com"] public class Course { [DataMember] public string Number; [DataMember] public string Title; [DataMember] public DateTime StartDate; } 

The data contract supports versioning. With the named property VersionAdded, you can specify additional elements that are added with newer versions as shown with the LocationCode. The property IsOptional specifies that messages from earlier versions of the contract are still accepted, as the LocationCode is an optional field.

[DataContract(Namespace="http://www.thinktecture.com"] public class Course {     [DataMember] public string Number;     [DataMember] public string Title;     [DataMember] public DateTime StartDate; [DataMember(VersionAdded=2 IsOptional=true] public string LocationCode; }

For being platform- and version-independent, using data contracts is the best way to define what data should be sent. However, you can also make use of XML serialization and runtime serialization. XML serialization was the mechanism used by ASP.NET Web services, .NET Remoting makes use of runtime serialization.

Message contract

A message contract is used if complete control over the SOAP message is needed. With the message contract you can specify what part of the message should go into the SOAP header, and what belongs to the SOAP body. The following example shows a message contract for the class ProcessPersonRequestMessage. The message contract is specified with the attribute [MessageContract]. The header and body of the SOAP message are specified with the attributes [MessageHeader] and [MessageBody]. By specifying the Position property, the element order within the body can be defined.

 [MessageContract] public class ProcessPersonRequestMessage { [MessageHeader] public int employeeId; [MessageBody(Position=0)] public Person person; } 

The class ProcessPersonRequestMessage is used with the service contract that is defined with the interface IProcessPerson:

 [ServiceContract] public interface IProcessPerson { [OperationContract] public PersonResponseMessage ProcessPerson( ProcessPersonRequestMessage message); } 

Service Implementation

The implementation of the service is marked with the attribute [ServiceBehavior] as shown with the class CourseRegistrationService:

 [ServiceBehavior] public class CourseRegistrationService : ICourseRegistration { public bool RegisterForCourse(Course course, Attendee attendee) { // implementation } } 

The attribute [ServiceBehavior] is used to describe behavior as is offered by WCF services to intercept the code for required functionality as shown in the following table.

ServiceBehavior Property

Description

AllowConcurrentTransactions

If incoming transactions should be allowed, you can set the property AllowConcurrentTransactions to true.

TransactionIsolationLevel

To define the isolation level of the transaction within the service, the property TransactionIsolationLevel can be set to one value of the IsolationLevel enumeration (Serializable, Repeatable, ReadCommitted, ReadUncommitted, Snapshot, Chaos, Unspecified.

AutomaticSessionShutdown

If the session should not be closed when the client closes the connection, you can set the property AutomaticSessionShutdown to false. By default, the session is closed.

InstanceMode

With the property InstanceMode you can define if stateful or stateless objects should be used. The default setting is InstanceMode.PerCall to create a new object with every method call. You can compare this with .NET Remoting well-known SingleCall objects. Other possible settings are PrivateSession and SharedSession. With both of these settings stateful objects are used. However, with PrivateSession a new object is created for every client. SharedSession allows sharing the same object with multiple clients.

ConcurrencyMode

Because stateful objects can be used by multiple clients (or multiple threads of a single client), you must pay attention to concurrency issues with such object types. If the property ConcurrencyMode is set to Multiple, multiple threads can access the object, and you have to deal with synchronization. If you set the option to Single, only one thread accesses the object at a time. Here you don't have to do synchronization; however scalability problems can occur with a higher client number. For stateless objects, this setting doesn't have any meaning as new objects are instantiated with every method call and thus no state is shared.

ReturnUnknownExceptionsAsFaults

With .NET, errors face up as exceptions. SOAP defines that a SOAP fault is returned to the client in case the server has a problem. For security reasons it's not a good idea to return details of server side exceptions to the client. Thus, by default exceptions are converted to unknown faults. To return specific faults, exceptions of type Fault<string> can be thrown.

ServiceBehavior Property

Description For debugging purposes, it can be very helpful to return the real exception information. This is the case when changing the setting of ReturnUnknownExceptionsAsFaults to true.

RunOnUIThread

If the service is offered by a Windows Forms applica- tion, invoking methods of UI controls always the same thread is needed. This is done automatically if you set the property RunOnUIThread to true.

ValidateMustUnderstand

The property ValidateMustUnderstand set to true means that the SOAP headers must be understood (which is the default).

Binding

A binding describes how a service wants to communicate. With binding, you can specify the following features.

  • Transport protocol

  • Security requirements

  • Encoding format

  • Transaction requirements

A binding is composed of multiple binding elements that describe all binding requirements. You can create a custom binding or use one of the predefined bindings that are shown in the following table.

Standard Binding

Description

BasicProfile

BasicProfile is the binding for the broadest interoperability, the first- generation Web services. Transport protocols used are HTTP or HTTPS; security is available only from the protocol.

WSProfile

WSProfile is the binding for the next-generation Web services, platforms that implement SOAP extensions for security, reliability, and transac- tions. The transports used are HTTP or HTTPS; for security the WS-Security specification is implemented; transactions are supported as has been described with the WS-Coordination; WS-AtomicTransaction and WS-BusinessActivity specifications; reliable messaging is supported with an implementation of WS-ReliableMessaging. WSProfile also sup- ports MTOM encoding for sending attachments.

WSProfileDualHttp

The binding WSProfileDualHttp in contrast to WSProfile supports duplex messaging.

NetProfileTcp

All standard bindings prefixed with the name Net use a binary encoding used for communication between .NET applications. This encoding faster than the text encoding with WSxxx bindings. The binding NetProfileTcpBinding uses the TCP/IP protocol.

NetProfileDualTcp

Contrary to NetProfileTcp, NetProfileDualTcp supports duplex messaging.

NetProfileNamedPipe

For communication between different processes on the same system, the NetProfileNamedPipe binding is the fastest binding.

NetProfileMsmq

The binding NetProfileMsmq brings queued communication to WCF. Here the messages are sent to the message queue.

MsmqIntegration

MsmqIntegration is the binding for existing applications that make use of message queuing. The binding NetProfileMsmq requires WCF applications both on the client and server.

Intermediary

The Intermediary binding is for intermediaries that sit between client and the service. HTTP, TCP, and named pipes are supported transport protocols.

Along with defining the binding, the service must define an endpoint. The endpoint is dependent on the contract, the address of the service, and the binding. In the following code, sample a ServiceHost object is instantiated, and the address http://localhost:9200/CourseRegistrationService as well as a WsProfileBinding instance is added to an endpoint of the service.

 using (ServiceHost<CourseRegistrationService> serviceHost = new ServiceHost<CourseRegistrationService>()) { // add a WSProfile endpoint to the service Uri address1 = new Uri("http://localhost:9200/CourseRegistrationService"); WsProfileBinding binding1 = new WsProfileBinding(); serviceHost.AddEndpoint(typeof(ICourseRegistration), binding, address); //... } 

Besides defining the binding programmatically, you can also define it with the application configuration file. The configuration for WCF is placed inside the element <system.serviceModel>. The <service> element defines the services offered. Similar as you've seen in code, the service needs an endpoint, and the endpoint contains address, binding, and contract information.

 <?xml version="1.0" encoding="utf-8" ?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.serviceModel> <services> <service serviceType="Wrox.ProCSharp.Indigo.CourseRegistrationService"> <endpoint address="http://localhost:9200/CourseRegistrationService" bindingConfiguration="CourseRegistrationConfiguration" bindingSectionName="wsProfileBinding" contractType="Wrox.ProCSharp.Indigo.ICourseRegistration" /> </service> </services> <bindings> <wsProfileBinding> <binding configurationName="CourseRegistrationConfiguration" securityMode="WSSecurityOverHttp" reliableSessionEnabled="true"> </wsProfileBinding> </bindings> </system.serviceModel> </configuration> 

Hosting

WCF is very flexible in choosing a host to run the service. The host can be a Windows service, a COM+ application, ASP.NET, a Windows application, or just a simple console application. Creating a custom host with Windows Forms, you can easily create a peer-to-peer solution.

The sample code shows hosting of a service within a console application. In the Main() method, a ServiceHost<> instance is created. After the ServiceHost<> instance is created, the application configuration file is read to define the bindings. You can also define the bindings programmatically as shown earlier. Next the Open() method of the ServiceHost<> class is invoked, so the service accepts client calls. With a console application, you have to pay attention not to close the main thread until the service should be closed. Here the user is asked to end the service.

 using System; using System.ServiceModel; public class Program { public static void Main() { using (ServiceHost<CourseRegistrationService> serviceHost = new ServiceHost<CourseRegistrationService>()) { serviceHost.Open(); Console.WriteLine("The service started. Press return to exit"); Console.ReadLine(); serviceHost.Close(); } } } 



Professional C# 2005
Pro Visual C++ 2005 for C# Developers
ISBN: 1590596080
EAN: 2147483647
Year: 2005
Pages: 351
Authors: Dean C. Wills

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net