From time to time I run into situations where people ask me, how they should implement a Service oriented architecture using service interfaces but keep enough generic behavior to cope with different usage scenarios. This is particular common with software vendors where you often have a stress ratio between implementing specific functionality but staying generic enough to be able to easily adapt to different customer scenarios.

This post is about how you are able to achieve both goals using some of the extensibility features coming with WCF. Actually this will be divided into multiple entries to keep the amount of stuff a little bit under control. In this first part I’ll look into the motivation for having explicit interfaces and how that is going to be beneficial for your application:

First let’s assume, we are about to develop a shop application and need to provide information about the customers using the shop. Take a look at the schema below.

This schema describes the structure of a given customer type with three attributes.

Following the contract first approach; you can represent the schema as a runtime type which can be serialized as xml data conforming the above schema. When you develop Services using WCF, this schema would map to the following .NET class:

For those of you who have ever used “Add Service Reference” or SVCUtil.exe, this class is not generated; however for the sake of brevity and clarity I prefer to use handcrafted sample code.

Now, let’s assume we were building a very simple CRM system. One use case from that system would be to implement a “Add Customer” service method, which can be used from “other” systems to add new customer instances to our CRM system.

Once again let’s follow the classic contract first approach and please take a look at the following WSDL document:

There is a port “ICustomerService” which consists of one service method “Add” with corresponding message definitions for the input (request) message and the output (response) message. If you want to know the exact layout of the input message you need to review the definition of tns:Add (http://SampleShop/Add) which can be found in the accompanying schema file:

 

When we take a closer look, we find that the required input message needs to consist of a Add Element containing a customer instance with FirstName, LastName and Birthday.

The Response message will only contain a empty AddResponse Element; in other words returns void.

We now have a complete definition of the service-interface (wsdl-port), the operation(s) and a specific description of the intended layout of messages to call the service.

Regarding the level of detail and lack of possible variances in the layout of the messages involved, we can call this a sample for an explicit service interface. The key benefit of such is that as a service consumer (client) all you need to know about the target system is the definition of the interface with its methods and types and no knowledge of the system internals (implementation). That is actually a design approach which is quite common in the industry since the raise of the component frameworks and is called “black box” design.

Now let’s have a look at an oppositional approach.

 

 

This schema is a variation of the http://SampleShop/Customer type we have seen before; However there’s a new Element “SomeData” of type anyType. The generated representation class from SVCUTIL.EXE would look like the following snippet:

This class introduces a Property “SomeData” of type System.Object which has the undesirable side effect, that you can never be sure whether it contains a simple bool or the complete Encyclopedia Britannica.

Despite the fact that we have at least some knowledge about the message structure involved, this is a common example to introduce extensibility into message-definitions.

Now let’s go one step further:

 

Now all we know is that the customer is a valid xml fragment; no schema, no knowledge of the structure of that type. This is an example for an implicit service interface. The good part is, this is totally flexible; I can use the very same service definition for all “customized” situations. The downside is I definitely must have internal knowledge of the target system, if I want to successfully communicate with it.

There are (rare) situations in distributed systems where one might prefer such approach; however, one must face the fact this violates one of the most fundamental principles of service orientation “Explicit interfaces”.

This creates the desire for a system offering explicit service interfaces without sacrificing the ability to flexibly adapt to different customer scenarios.

The next post of the series will show how to use the facilities of the WCF Metadata extensibility to achieve just that.