Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C#

WCF: The Right Way. A Quick Reference Guide

4.77/5 (17 votes)
3 Oct 2010CPOL6 min read 71K   1.9K  
A developer workflow of the manual way of creating and consuming WCF Services developed by Miguel Castro

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.

vs_new_project_dialog.png

Figure 1: MC recommends not using the template "WCF Service Application"

vs_add_service_reference_dialog.png

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

vs_solution_explorer_1.png

vs_solution_explorer_2.png

Figure 3: The service related projects
Figure 4: The transport related projects

vs_solution_explorer_3.png

Figure 5: The user interface project

This task can be broken into four categories:

  1. 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
  2. Setting up the transport
    • For a WebService:
      • Add the "Service Host" project
      • Add a new Project > ASP.NET Web Application > name ends in "WebService"
      • Add a reference to the Service project
      • Delete Default.aspx
      • Add one text file for every service class and change the filename extension to SVC
      • Add the following code template (inserting the namespace of the service classes) to the files:
      ASP.NET
      <%@ ServiceHost
          Service ="namespace.of.service"
      %>
    • Add the "Client Proxy" project
      • Add a new Project > Class Library > name ends in "ClientProxy "
      • Add references to System.ServiceModel
      • Add a reference to the Contract project
      • Add a class for each Interface in the Contracts
      • In each class:
        • Add a using clause for System.ServiceModel
        • Implement the interface
        • Inherit ClientBase<TheInterface>
        • In each method, reference the service method through the base Channel property
  3. 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
  4. 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

  1. 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
  2. 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)