Click here to Skip to main content
Click here to Skip to main content
Go to top

WCF for the Real World, Not Hello World

, 31 Jul 2014
Rate this:
Please Sign up or sign in to vote.
WCF development for real RAD in enterprise

Introduction 

Presumably you have created a few commercial WCF projects. If not, it is recommended that you create a few Hello World projects first for getting hand-on experiences in WCF. There are tons of tutorials in the Internet for creating a Hello World WCF project, like Implementing a Hello World WCF Project, and Implementing a WCF Service in the Real World. This article is to demonstrate how to efficiently and effectively manage WCF service development in enterprise environment through team works in order to rapidly develop and deliver decent Web services.

 

Hello World

You know how good WCF is, and how convenient building Web services using the “WCF Service Application” template is. With simply a few mouse clicks, the VS IDE creates a set of skeleton codes for you so you could rush to coding business features right away, as illustrated in the following screenshots you are already familiar with.

image   image

For small projects, say less than 2000 lines in the WCF modules, the template has provided a decent RAD support. I used these templates in my early days of programming WCF as well.  However, what crafted by the template has a few vulnerabilities against the productivity of the whole SDLC.

  1. Having the abstract interface and the concrete implementation in the same package (assembly) is smelly.
  2. The service contract and the data contract have no namespaces defined.

Vulnerability 1 destroys the abstraction and the separation of concern which are the keys for managing complexity.

Without explicitly defining namespaces,  the default namespaces are used, namely, http://tempuri.org for operation contracts and http://schemas.datacontract.org for data contracts, and the second URL is owned by Microsoft. While this sounds trivial, however, this is not a good publicity to your company which is apparently not owned by Microsoft. In addition, when you have a lot data contracts to handle, sooner or later you are going to hit the wall. For example, if you have over one hundred data contracts all living in the same default namespace http://schemas.datacontract.org, it is not unlikely programmers will create 2 contracts named “CompositeType” or alike, then these 2 data contracts could hardly live in the same AppDomain, since data types in the same schema namespace will be likely transformed into classes in the same CLR namespace. This is especially true if BizTalk is involved in system integration, which is an information hub of enterprise architecture. Not explicitly defining namespaces is exchanging hassles in the future, and particularly high costs in maintenance.

Real World

In enterprise environment, WCF is a powerful and convenient framework for wrapping up new business components and legacy applications. The complexity of the whole development work soon require great degree of separation of concerns and separation of responsibilities into these areas:

  1. Interface design
  2. Implementation
  3. Testing  
  4. Configuration
  5. Client programming

WCF provides inherent supports for such separations. For some reasons, those templates coming with VS hide and limit such power of WCF, though they are good enough to deliver your first WCF solution ASAP, and get applause from your boss. However, if you want to deliver elegant solutions for complicated problems in efficient way, you have better to follow the SOLID OOD principles and separate concerns as much as possible. Otherwise, you will have to work harder, rather than smarter, when the project evolves and resolve more complicated problems.

In a typical enterprise application, classes of different life cycles has better to stay in different packages, or in different Visual Studio solutions, or even in different revision control repositories. Planning for such arrangement is essential for improving maintainability and flexibility in order to lower the costs and improve productivity and quality. In addition, the build time could be reduced.

The following screenshot illustrate the basic structure of a simple real world project.

image

Create project RealWorldService with contracts only 

namespace Fonlow.Demo.RealWorldService
{
    [ServiceContract(Namespace = "http://www.fonllow.com/demo/RealWorldService/2012/08")]
    public interface IService1
    {
        [OperationContract]
        [FaultContract(typeof(Evil666Error))]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
    }

    [DataContract(Namespace = "http://www.fonllow.com/demo/RealWorldService/Data/2012/08")]
    public class CompositeType
    {

        [DataMember]
        public bool BoolValue
        {
            get;
            set;
        }

        [DataMember]
        public string StringValue
        {
            get;
            set;
        }
    }

    [DataContract(Namespace = "http://www.fonllow.com/demo/RealWorldService/Data/2012/08")]
    public class Evil666Error 
    {
        [DataMember]
        public string Message { get; set; }
    }
}

And the project also contains a batch file of generating WSDL.

cd %~dp0
:: generate wsdl. Run this when there's a breaking change in the interface. 
   You still need to be careful about interface versioning.
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\
  svcutil.exe" bin\Debug\Fonlow.RealWorldService.dll /directory:..\deployment 

Create project RealWorldImp for implementation 

namespace Fonlow.Demo.RealWorldService
{
    public class Service1 : IService1 
    {
        public string GetData(int value)
        {
            if (value == 666)
                throw new FaultException<Evil666Error>(
                  new Evil666Error() { Message = "Hey, this is 666." });

            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }

            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

Create project TestRealWorld for unit test 

[TestMethod]
public void TestGetData()
{
    IService1 service = new Service1();
    Assert.IsTrue(service.GetData(1234).Contains("1234"));
}

It is more handy to unit test a service function as an in-process function.

Create RealWorld Web service with IIS

Steps

  1. Create a Web site http://localhost:8998 in C:\inetpub\wwwroot\RealWorld with an application pool of .NET 4.
  2. Copy assemblies of project RealWorldImp to the bin directory of the Web site

Step 2 can be done through the post build event of project RealWorldImp.

image image

Create project RealWorldServiceClientApi

 The class library project should has references System.ServiceModel and System.Runtime.Serialization.

The codes of this project and the client config are generated by a batch file named CreateClientApi.bat.

cd %~dp0
rem generate client proxy classes with the wsdl
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\svcutil.exe" 
  ..\deployment\*.wsdl ..\deployment\*.xsd /language:C# /n:http://www.fonllow.com/demo/RealWorldService/2012/08,
  Fonlow.RealWorldService.Clients /n:http://www.fonllow.com/demo/RealWorldService/Data/2012/08,
  Fonlow.RealWorldService.ClientData /o:RealWorldClientApiAuto.cs /config:appAuto.config

The client API assembly and the config file could then be used by your client programs, including the integration test suit.

Hints

If your Web services will be consumed by other IT vendors which use .NET for software development, you may provide the client API to them so they could rapidly develop applications consuming your Web service.

Notes that I named those generated files with Auto suffix, so I could exclude them when running some static code analysis tools like Source Monitor.  

Create project TestRealWorldIntergration for integration test

This project is the first consumer of the client API.

image

const string realWorldEndpoint = "DefaultBinding_RealWorld";

[TestMethod]
public void TestGetData()
{
    using (Service1Client client = new Service1Client(realWorldEndpoint))
    {
        Assert.IsTrue(client.GetData(1234).Contains("1234"));
    }

    using (Service1Client client = new Service1Client(realWorldEndpoint))
    {
        try
        {
            Assert.IsTrue(client.GetData(666).Contains("1234"));
            Assert.Fail("Expect fault");
        }
        catch (FaultException<Evil666Error> e)
        {
            Assert.IsTrue(e.Detail.Message.Contains("666"));
        }
    }

}

Hints: The source codes of both Hello World and Real World are here.

How real is this Real World service?

The construction of this Real World service is not utilizing many handy features provided by the IDE Wizards, and require some more manual steps to setup the project structures. What is the bargain?

Please do consider, in a decent Web service development project, the majority of project time is spent on analysis, interface design, implementation and testing. The time saved by the Wizards is very insignificant, however, the costs bought by the “poor” structures created by Wizard will be long standing, and haunting you soon. In the future, I may be presenting some negative case studies about how poor practices of software engineering using WCF bring low productivity of software development and poor quality of the service.

Here I would just try to explain how to establish positive experience of developing Web services using WCF.

Separating the interfaces and the implementation into two assemblies

I believe that you have heard of and studied separation of concerns many times in your career as software developer. Why separation of concerns?

Separation of concerns is a computer science principle that promotes separating the responsibility for an application or use case across multiple components, where each component has a distinct, small set of responsibilities. 

IMHO, this is to manage complex and volatile requirements using the very limited capacity of our human brain, so we are able to design working and maintainable solutions against complicated problems, and respective team work during development could be more efficient. In contrast, computers do not care about separation of concerns, and the loosely coupled components during software development will be glued together at run time after all.

 

Putting the abstraction and the concrete implementation in the same package is a significant design smell. Why?

The life cycles of the abstraction and the implementation tend to be greatly different. The abstraction is usually stable, once defined, rarely change or even should not change, for example, interfaces once published should not be changed. The implementation are subject to improvement and bug fixing.

 Generate WSDL from the assembly that defines contracts

The assembly that defines contracts has enough info for generating WSDL, and the Web service that is configured to publish WSDL simply reads info from the assembly and generate WSDL on a fly. So you should not need to run the Web service first before getting the WSDL.

In a large project of distributed computing, it is often desired to start the client programming before the service implementation is done. With the WSDL, you could use .NET SDK to generate a mock implementation of the Web service. The client programmers may then use the mock Web service for constructing and testing client programs. And you as service developer may use a copy of the mock service codes to start implementing the Web service. Please note, the client programs of the WCF service might be coded in Java or PHP. Java programmers and PHP programmers may then import the WSDL to generate client proxy classes. 

Not using the built-in Web server of VS

Probably you have heard that testing in an environment as similar as possible to the production environment. Since we are going to host the service in IIS, why not test it all the time with IIS?

You will get clear idea how your services perform. In addition, please consider this scenario.

You have developed and tested a Web service using VS IDE, then give the package to the system admin who will install and test in another environment. It is not uncommon that the Admin comes back to you and say “It doesn’t work”. You are puzzled, “It works in my computer, see, the client and the service works beautifully in harmony”. And the admin may be responding: “Do we run Visual Studio in our staging environment?”.

If you test all the time with IIS in your development machine, you may say, “It works on my IIS instance, shall we examine the difference between your IIS and my IIS?”. Do you think this sounds more pleasant to the system admin? 

Unit testing

Shall I explain more?

Probably here is not a good place to explain the benefits of unit testing. I would just say how bad it could be without unit testing. Without covering your service implementation as much as possible, you will spend many more hours on debugging through attaching your codes with a hosting process.

Integration testing

Here I use MS Test as test harness. And you may use NUnit or other test harness frameworks to construct automatic integration testing. Even if your unit tests have covered the implementation as much as possible, there are still some features of the Web service can’t be tested through unit testing, for example, service behaviors and fault contracts etc.. The integration testing is basically a client program of the Web service, talking to the service through HTTP typically.

Depending on your company’s system configuration, it might be handy to develop the integration tests using NUnit as a test harness. So after the system administrator has installed the service, the administrator may run the tests right away to verify the deployment before the service is open for business.

Client API

A typical WCF tutorial you could find in MSDN or the Internet adds Service Reference to the consumer project, pointing to the WSDL of a running Web service or a static WSDL file, and IDE will create the client API codes within the consumer project.

Through building a client API assembly, multiple consumer projects might enjoy the same client API library, saving the efforts of generating client API codes in each consumer project. Amazon and Google typically provide client API libraries in .NET, Java, and PHP, in addition to publishing WSDL.  So this is a common practice well proven in prominent software development shops.

In addition to reducing duplicate codes generated, you have better control over the namespaces of the client proxy classes. Such practice is even more beneficial when versioning of the service is needed.  

If interoperability of the Web service is a part of the requirement, you may use other software development platforms such as NetBean to create client codes from the WSDL. In fact, I have seen legacy Web services in productions coded in WCF could not be consumed by non .NET platforms, and then the costs of supporting new types of client programs were huge.

Summary 

The WCF templates of Visual Studio and respective Hello World tutorials are good enough for the following scenarios: 

  1. Hello World projects
  2. Prototype  
  3. Small projects in small companies
  4. Contract works without QA

For large and complex projects, those shortcuts or conveniences provided by IDE will soon become liability giving more troubles than good. We have better to program into WCF, rather than program in Visual Studio WCF. Have you heard of “Program into your language, not in it”?

Please note, this article is not about a template for every WCF projects. Do you really need to remember all these steps of creating a real world WCF project?

I don’t. However, I had already grown such habit based on these principles or practices of design:

  • Separation of concerns. In particular, separate abstraction and implementation. And at coding level, put them into different VS projects.
  • Understand the basic, respect related standards and conventions
  • Prepare for fast changing requirements
  • Test early

Many had considered that using WCF is a RAD way of developing Web services, and skipped understanding the basic (not only the basic of WCF, but the basic of Web service). Unfortunately, such practices always lead to Slow and Buggy Application Development: rapid only at the beginning of coding. People might had developed business application features rapidly, however RAD had often become Rough Application Delivery, costing everyone dearly.

In the real world, the business / functional requirements keep changing. The problems or market demands keep evolving, and our understanding about the problems or demands are evolving too, given the same problems and demands. A good design or a good practice is to solve complicated things through least complex solutions, while taking care of volatile requirements through Agile practice.

The good thing of WCF is making it easy to practice decoupling, and realize the integration during deployment through configuration. The software development requires decoupling for productivity, quality, flexibility and maintainability, while the system integration will bind components together to deliver services according to many environmental factors. WCF takes care of both worlds, provided you understand the basic of Web services and OOD.

This article is intended to be a stepping stone for you to learn more about managing complex projects of distributed computing using WCF.

References for Hello World: 

References for Real World

License

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

Share

About the Author

Zijian
Software Developer
Australia Australia
I started my IT career in programming on different embedded devices since 1992, such as credit card readers, smart card readers and Palm Pilot. Programming on the hardware was really fun, feeling like driving the hardware directly.
 
Beside technical works, I enjoy reading literatures, playing balls, cooking and gardening.

Comments and Discussions

 
QuestionMy vote of 5 and comment for a tool for Contract First WCF development -> http://wscfblue.codeplex.com/ Pinmemberpopart31-Jul-14 23:45 
GeneralMessage Automatically Removed PinmemberKasia Kowalska31-Jul-14 4:51 
GeneralMy vote of 5 PinmemberGregoryW24-Sep-13 23:05 
QuestionSample app PinmemberMohammed Hameed23-Sep-13 0:01 
AnswerRe: Sample app PinmemberZijian23-Sep-13 0:12 
GeneralRe: Sample app PinmemberMohammed Hameed23-Sep-13 4:54 
GeneralMy vote of 5 PinmemberMohammed Hameed22-Sep-13 23:57 
GeneralMy vote of 5 PinmemberSouthmountain2-Aug-13 8:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 31 Jul 2014
Article Copyright 2013 by Zijian
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid