Part 2 now available on Code Project at http://www.codeproject.com/WCF/edujini_wcf_scart_02.asp.
Also posted here at EduzineĀ©.
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 applications. 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.
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. I will keep posting as and when they are 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 here
- Microsoft .NET Framework 2.0 SDK here
- Microsoft .NET Framework 3.0 Redistributable here
- Microsoft Windows SDK for Windows Vista and .NET Framework 3.0 Runtime Components here You may download the complete image here
- If you are working with Visual Studio, download the extensions here
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 the 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 purposes.
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 a 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.
="1.0"="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 the .NET 3.0 SDK is installed (default location being %PROGRAMFILES%\Microsoft 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 a reference to System.ServiceModel.dll. Build your project. Execute the client. You should get an output similar to that 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. 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.
Contact
- You may directly put a comment below and I shall respond.
- You can contact me directly at gaurav.vaish@gmail.com.
- If you are looking for any professional work on Microsoft .NET Framework 2.0/3.0, Java 1.5/1.6, Web Services or Service Orientated Architecture (SOA), please contact my employer Edujiniā¢ Labs at http://www.edujini-labs.com.
Version History
- Initial submission
- Updated introduction to something better than previous one
- Provided details of the 2nd article of the series - now available at Code Project