Starting with this article, we shall explore various aspects of WCF.
Introduction
Microsoft .Net Framework 3.0 introduces, among other components, Windows Communication Foundation or simply, WCF. The framework
allows us, the development community, to build more service-oriented application. It incorporates several Web Service related
specifications, mostly driven by W3C and OASIS consortiums. I will just list a few of them:
- SOAP 1.1, 1.2 with Basic Profile 1.1
- WSDL 1.1
- MTOM
- WS Policy and WS Policy Attachments
- WS Metadata Exchange
- WSS SOAP Message Security 1.0, 1.1
- WSS SOAP Message Security Username Token Profile 1.0, 1.1
- WSS SOAP Message Security X.509 Token Profile 1.0, 1.1
- WS Addressing 2005/08
- WSS SOAP Message Security Kerberos Token Profile 1.1
- WS Secure Conversation
- WS Reliable Messaging
- WS Coordination
- WS Atomic Transaction
- WS Federation
Starting with this article, let us tour various key aspects of WCF.
Downloads
The code for the project is available for download at Edujini Downloads in the Windows Communication Foundation category.
Case Study
We shall take a simple shopping cart as a case-study. We start with simple data-types and slowly build on to work
with custom, more complex data-types. In the sequence of articles, we shall explore various key aspects of WCF.
The minimum features that I wish to explore in the series are:
- Publishing WCF Service
- Writing WCF Client
- Customising the operation contract details, say decoupling the .Net and contract names or pushing part
of the content in
Headers of the Soap-Envelope
- Working with faults and errors
- Working with custom data-types
- Working with generic data in operations
- Working with interface-types in operations
- Working with collections in operations
- Working with large data in operations
- Working with sessions and transactions
Yeah.. it's a long list, but I'll try to fulfil my promise. No, all the articles are not ready right now.
Will keep posting as and when ready, and also update this article with references to them.
Ok.. so, let's start!
We will need the following items to work with WCF:
- Microsoft .Net Framework 2.0 Redistributable
- Microsoft .Net Framework 2.0 SDK
- Microsoft .Net Framework 3.0 Redistributable
- Microsoft Windows SDK for Windows Vista and .Net Framework 3.0 Runtime Components
You may download the complete image here
- If you are working with Visual Studio, download the Visual Studio Extensions
Service Definition
Our shopping-cart service, to begin with, publishes the following operations:
bool CheckUserExists(string username);
DateTime? GetLastTransactionTime(string username);
The job of the first operation is to check whether or not the user is registered in our database or not.
The second operation returns the date and time of last transaction done by the last user, if any. Yes, you note
the operation correctly, the return type is not System.DateTime but System.DateTime?,
the C# syntax for System.Nullable<System.DateTime>
To publish any service in WCF, we require four steps in general:
- Service contract definition
- Contract implementation
- Service configuration
- Service hosting
In WCF, service contract is the term used for the final service being published. Note that a service may have one or more related
operations, referred to as operation contracts in WCF.
If you are working in Visual Studio, create a new project of type "Class Library". Yes, you read it right, it is
"Class Library" and not "WCF Service Library".
We start by creating an interface IShoppingCartService as follows:
using DateTime;
namespace ShoppingCartLibrary
{
public interface IShoppingCartService
{
bool CheckUserExists(string username);
DateTime? GetLastTransactionTime(string username);
}
}
The next obvious step is to provide implementation to the service. We create a class ShoppingCartImpl
that implements the interface IShoppingCartService.
using DateTime;
namespace ShoppingCartLibrary
{
public class ShoppingCartImpl : IShoppingCartService
{
public bool CheckUserExists(string username)
{
if(username == "gvaish" || username == "edujini")
{
return true;
}
return false;
}
public DateTime? GetLastTransactionTime(string username)
{
if(username == "gvaish")
{
return DateTime.Now.AddDays(-3);
}
if(username == "edujini")
{
return DateTime.Now.AddHours(-3);
}
return null;
}
}
}
We need configuration at two levels:
- Using attributes, we need to tell WCF about the service
contract and operation contracts. The information would be used to define service, operations, messages and types
- Using configuration entries, we need to tell WCF about the implementation class to be
used and binding details. These details would be used for hosting purpose.
If you are using Visual Studio, add a reference to the assembly System.ServiceModel.dll from GAC.
Add the attribute System.ServiceModel.ServiceContractAttribute to the interface. It tells the WCF that
there is a service associated with the corresponding type.
Add the attribute System.ServiceModel.OperationContractAttribute to the methods in the interface. It informs the
WCF about the operations to be published in the service. It will take care of messages and types associated on its own.
So, our final code looks as follows:
using DateTime;
using ServiceModel;
namespace ShoppingCartLibrary
{
[ServiceContract]
public interface IShoppingCartService
{
[OperationContract]
bool CheckUserExists(string username);
[OperationContract]
DateTime? GetLastTransactionTime(string username);
}
}
We shall provide these details to our hosting application.
Compile the files to the assembly. I name it ShoppingCartLibrary.dll. If you are compiling
the code at the commandline, do not forget to add reference to System.ServiceModel.dll.
Having defined our service completely, we need a runtime (engine) to host the service - an application that can allow
the clients to connect and invoke the operations. For this, we shall create a console application. The application
has just one class, MainClass, with the Main method.
For Visual Studio users, we name the project as ShoppingCartHost. Rename the class
Program to MainClass.
Add reference to System.ServiceModel.dll and to the ShoppingCartLibrary.dll
Write the following code to the MainClass.
using System;
using System.ServiceModel;
using ShoppingCartLibrary;
namespace ShoppingCartHost
{
public class MainClass
{
public static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:8080/ShoppingCartService");
using(ServiceHost host = new ServiceHost(typeof(ShoppingCartImpl), uri))
{
host.Open();
Console.Write("Hit <enter> to stop service...");
Console.ReadLine();
}
}
}
}
Now, we need the service configuration as mentioned earlier.
Write the following code to the application configuration file.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="HttpGetBehaviour">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ShoppingCartLibrary.ShoppingCartImpl"
behaviorConfiguration="HttpGetBehaviour">
<endpoint binding="mexHttpBinding"
contract="ShoppingCartLibrary.IShoppingCartService" address=""/>
</service>
</services>
</system.serviceModel>
</configuration>
Compile your code. Start the console application. You should see your server up and running.
Browse to the location http://localhost:8080/ShoppingCartService.
Hurray! We are ready with our first service. Let's now design a client to consume the service.
Client Application
For our client, we need two items: the proxy client code and the configuration items. No no, you don't write any of them.
You can generate them using the WCF tool svcutil.exe. You can locate this tool in the folder where your Visual Studio
IDE is installed (default location being %PROGRAMFILES%\Microsoft Visual Studio 8\Common7\IDE) or where you install
the .Net 3.0 SDK is installed (default location being %PROGRAMFILES%\Micrsofot Windows SDK\v6.0\bin).
Ensure that the location to svcutil.exe is in your path. Invoke the following at commandline.
svcutil.exe /nologo /config:App.config http://localhost:8080/ShoppingCartService?wsdl
It will generate two files: ShoppingCartImpl.cs and App.config. We just need a MainClass
with Main method on the client side to consume the service published. Write the following code to the class:
using System;
namespace ShoppingCartConsumer
{
public class MainClass
{
public static void Main(string[] args)
{
ShoppingCartServiceClient client = new ShoppingCartServiceClient();
string[] users = new string[] { "gvaish", "edujini", "other" };
foreach(string user in users)
{
Console.WriteLine("User: {0}", user);
Console.WriteLine("\tExists: {0}", client.CheckUserExists(user));
DateTime? time = client.GetLastTransactionTime(user);
if(time.HasValue)
{
Console.WriteLine("\tLast Transaction: {0}", time.Value);
} else
{
Console.WriteLine("\tNever transacted");
}
}
Console.WriteLine();
}
}
}
Don't forget to add reference to System.ServiceModel.dll. Build your project.
Execute the client. You should get an output similar to shown below:
Note that this is only a start... so, please have a little patience if you are looking for advanced topics.
Notes
We chose to have an interface as our service contract. In general, we can have a class directly as a service contract.
However, it is always a good idea to have an interface and then provide an implementation. In this way, we can keep and
maintain the declaration of the contract and implementation of the contract independently and modularly.
Summary
With WCF, it is possible to publish and consume web services in a very simple way. Although publishing a web service
is not as simple as in ASP.Net. However, as may be seemingly noticeable, the WCF may turn out to be much more flexible
than ASP.Net service. One of the flexibilities that we saw was to host it outside ASP.Net Runtime.