Introduction
Miguel Castro (MC from now on) gives a compelling argument why the included project templates for WCF Service Applications "creates too much baggage" and does not promote "best practices". He continues by suggesting adding service references is also "falling a bit short". To put it in context, he notes that WCF "is probably one of the absolutely coolest technologies to come out of Microsoft".
The WCF template method does not separate the contracts, tightly couples the service to a web-service (although other transports can be used), web-service webconfig contains too much metadata, and service references duplicate contracts.
A summary of MC’s Critique can be found here. What turns this article into a constructive exercise is that he also outlines a manual way of creating and consuming WCF services: that is loosely coupled, follows good design standards, and most importantly, is simple to maintain. This article breaks his process into a concise developer workflow, broken into distinct actions and steps - a Quick Reference Guide.
|
Figure 1: MC recommends not using the template "WCF Service Application"
|
|
Figure 2: MC recommends not referencing WCF services using the "Add Service Reference" function.
|
Conventions
- In the projects, any non-default entries in configurations files (Web.config and App.config) are added to a folder called Configuration and
configSource
links are added to the configuration file. - A WPF client is used for demonstration purposes only. Any client that can make WCF service calls can be used.
- A Webservice and TCP Host are provided in the demo code. Other transports can also be used. Webservices are broken down in the article.
- The steps below assume a new solution has been created and .NET Framework 3 + is available for development.
Setting Up Projects
The solution is separated into the following projects (showing functions and benefits of separation):
- Model
- Functions - The business object definitions
- Benefits - Typical separation; reuse among different assemblies
- Contract
- Functions - Service and data contracts
- Benefits - Reuse in service and consumer of service (to SOA principals)
- Service
- Functions - One or more; contains service methods based on contracts
- Benefits - Reuse in other solutions; procedural entry point into object model
- Service Host
- Functions - Referenced by the proxy; provides the transport to the service
- Benefits - Allows multiple transports (through other service hosts) to use the services
- Client Proxy
- Functions - Consumer entry point to access a service’s implementation
- Benefits - Reuse among multiple clients; can use different endpoint names for reuse on different service hosts
- Client
- Functions - Service client or consumer
- Benefits - Typical separation; can use various transports to services
|
|
Figure 3: The service related projects
| Figure 4: The transport related projects
|
| |
Figure 5: The user interface project
| |
This task can be broken into four categories:
- Setting up the Service layer
- Add the "Model" project
- Create a new Project > Class Library > name ends in "Model"
- Add a reference to
System.Runtime.Serialization
- Add a Class for each business object you intend to use
- Add a
using
clause for System.Runtime.Serialization
in each of those classes - Add the
DataContractAttribute
to the classes - Add the
DataMemberAttribute
to the public
members of the classes
- Add the "
Contract
" project
- Add a new Project > Class Library > name ends in "
Contract
" - Add Interfaces for each of the service classes you intend to use
- In each interface, add a reference to
System.ServiceModel
- Add the
ServiceContractAttribute
to the Interface. - Add the
OperationContractAttribute
to the members of the interface.
- Add the "
Service
" project
- Add a new Project > Class Library > name ends in "
Service
" - Add a reference to the Model and Contract projects
- Add a class for each interface you have added to the "
Contract
" project - In each class, add a
using
clause for Model
and Contract
projects - Implement each interface
- Setting up the transport
- Setting up the consumer
- For a WPF client:
- Add a new Project > WPF Application > name ends in "
WpfUi
" - Add a reference to
System.ServiceModel
- Add a reference to the
ClientProxy
, Model
and Contract
projects - Add endpoints for the service classes in the
App.config
in the configuration
/system.serviceModel
/client
element - In the class(es) where the service calls are made:
- Add a
using
clause for System.ServiceModel
, ClientProxy
, Model
and Contract
projects
- To call the service:
- Create a new proxy object
- Evoke the method of the proxy that maps to the service method call
- Configuring the solution
- Set the start up projects
- To debug a local
TcpHost
project
- Right-click the Solution in the Solution Explorer > Properties
- Choose Startup Project > Multiple Startup Projects
- Select the
TcpHost
and WpfUi
projects
Common Maintenance Tasks
- Adding a service
- Create an
Interface
for the service - Implement the
interface
in a new class in the Service
project - Create a class in the
ClientProxy
that Implements ClientBase
and the new interface
referencing the service - Create a SVC file (renamed from a text file) that maps to the service namespace in the
WebService
- Create an
endpoint
in the UI project that maps to the SVC file nominating the contract (interface) - Create an endpoint in the
WebService
that points to the Service
class - Consume the service using the
ClientProxy
class
- Adding a service method
- Create an
interface
definition for the method - Implement the method in the
Service
class of the Service
project - Add a method to the
ClientProxy
class - Consume the service method using the
ClientProxy
class
Points of Interest
The ClientProxy
constructor has a parameter endpointConfigurationName
which is passed to the ClientBase
constructor. This was only used so that service calls could be routed to either transport (TCP/HTTP) from the consumer. In real world applications, this is an unlikely scenario, and this can be removed. A single endpoint would be defined for the contract.
Conclusion
Using the cool technology that is WCF does not mean you have to forfeit good design principles. Miguel Castro has broken it down. This article summarizes the developer workflow used to implement his method.
History
- 2010-10-04 - Add
WebService
endpoint in "Adding a service" - 2010-10-01 - Initial submission