Implementing and testing web services in Visual Studio (2010) using
Windows Communication Foundation (WCF) is very easy.
Let's say we want to create
Calculator service which exposes methods that return results of addition, subtraction, multiplication and division applied on provided operands. These operations always take two operands so we can group them in a class
Operands.
Now we can define interface of such web service:
Once we have have a clear image of exposed web methods and data types we can start implementing web service. In Visual Studio (I am using VS2010), go to
File ->
New ->
Project... and create Visual C#
WCF Service Library project named
CalculatorServiceLibrary. Make sure you are using the latest .NET Framework (e.g. version 4.0). Visual Studio creates project skeleton with following files:
IService1.cs (service
interface definition file):
Service1.cs (service
interface implementation file):
App.config:
These auto-generated files give us a hint how to organize the code and we need to modify them, inserting specifics of our service.
WCF is a framework for building
Service Oriented Architecture (SOA) applications. SOA requires defining protocols on messages and data exchanged between service and client. They are known as Service and Data Contracts and are supported by WCF.
Web Service interface definition file contains these contracts.
Service Contract defines operations exposed by the service.
[ServiceContract] attribute applied to an interface (or class) tells it represents a service contract. Interface or class methods that are to be exposed as service operations are marked with
[OperationContract] attribute.
Data exchanged between client and service (service operations arguments and return values) is described through
Data Contract. All data is embedded into SOAP messages which are XML-based so data types must be serializable. All primitive .NET types are serializable by default and have default data contracts. But custom types that are part of data contract must be marked with
[DataContract] attribute which defines them to be serializable. Type members that are part of data contract must be marked with
[DataMember] attribute.
In our case, custom data type is class
Operands and we need to mark it as
[DataContract]. We can rename
IService1.cs and
Service1.cs to
ICalculatorService.cs and
CalculatorService.cs. After modifying the interface, its implementation class and data type, these files look like this:
ICalculatorService.cs:
CalculatorService.cs:
[ServiceBehavior] attribute controls various aspects of service object behaviour. In our case we specified that there will be only a single instance of the service object created on the server and that only a single thread at a time will be allowed to process method calls. This means that one client would need to wait for another's client web method call to complete. In our simple example this is acceptable but if amount of processing within web methods was higher, a different behaviour model would need to be applied.
Before compiling our project we yet need to modify application configuration file (
App.config). Let us rename service to
"CalculatorServiceLibrary.CalculatorService" and name behavior as
"MetadataEnabled". In order to enable generating WSDL we need to add reference to this behavior as a service attribute:
behaviorConfiguration="MetadataEnabled" and add
httpGetUrl="mex" to
behavior's
serviceMetadata element. URL of the WSDL can now be made by appending
"/mex" to the base address.
By default, service endpoint binding is set to
wsHttpBinding which encrypts messages. For our convenience, as we will be using HTTP sniffer later, let us apply
basicHttpBinding, which does not apply encryption. This way we will be able to see unencrypted data in HTTP messages exchanged between server and client.
Yet another thing set by default is to be changed: service endpoint contract - let us rename it to
"CalculatorServiceLibrary.ICalculatorService".
App.config will have the final look:
We are now ready to build this project. If we build it in Debug mode, project's
Debug directory will contain
CalculatorServiceLibrary.dll and
CalculatorServiceLibrary.dll.config. This config file is a pure copy of
App.config visible and editable from Visual Studio.
We can test our web service from Visual Studio if we run the project (press F5 key). This will start
WCF Service Host and
WCF Test Client tools. Service will automatically be deployed on the host and the client will use published metadata information in order to build a list of web methods (matadata is fetched from endpoint that implements
IMetadataExchange contract). We can type in arguments and invoke web methods in the Test Client.
WCF Service Host:
WCF Test Client:
In order to see generated WSDL we can copy metadata address (WSDL URL; in our example:
http://localhost:8732/Design_Time_Addresses/CalculatorServiceLibrary/Service1/mex) from Web Service Host and paste it into a web browser:
Generated WSDL for this service is:
We can run
WCF Service Host out of Visual Studio, from command prompt:
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>WcfSvcHost.exe /service:"c:\DEVELOPMENT\RESEARCH\C#\WCF\Web Services\CalculatorServiceLibrary\CalculatorServiceLibrary\bin\Debug\CalculatorServiceLibrary.dll" /config:"c:\DEVELOPMENT\RESEARCH\C#\WCF\Web Services\CalculatorServiceLibrary\CalculatorServiceLibrary\bin\Debug\CalculatorServiceLibrary.dll.config"
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>
If this instance of the host cannot create endpoint (cannot listen) on the port 8732 (because previous instance run from Visual Studio has locked it), enter some other port number in
baseAddress in
App.config (e.g. 8733).
From another instance of cmd.exe, we can run
WCF Test Client:
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE>WcfTestClient.exe http://localhost:8732/Design_Time_Addresses/CalculatorServiceLibrary/Service1/mex
Client and host exchange
SOAP messages (request and response) during web method calls. We could see the content of those SOAP messages by using some
HTTP sniffer. In my next article, "
How to sniff SOAP messages exchanged between WCF Service Host and Test Client" I will describe how to set
Fiddler Web Debugger in order to capture HTTP traffic between these two applications.
Links and References:
What Is Windows Communication Foundation (MSDN)
Windows Communication Foundation (Wikipedia)
Designing and Implementing Services (MSDN)
Using Data Contracts (MSDN)
Sessions, Instancing, and Concurrency (MSDN)