Welcome to EMC Consulting Blogs Sign in | Join | Help

Simon Evans' Blog

My blog covers the technology areas I focus on here at EMC Consulting, namely Architecture using the .NET Framework, ASP.NET, WCF, WCF Data Services and Windows Azure Follow me on twitter @simonevans

WCF Contract Design Guidelines

Here at Conchango we have community days every six weeks where we get together to discuss common work interests. As a .Net Architect, one of the core communities I participate in is the .Net community. At our last community day, I presented on Windows Communication Foundation, a technology I have been working with in anger now for over a year.

Whilst the PowerPoint slideshow doesn't really cover any detail on what I presented or demonstrated, I thought I'd attach it to this blog anyway, as this blog covers the contract design guidelines I ran through with the community.

Overview

The following design guidelines can mostly be based around one single important fact about implementing a service orientated architecture (SOA); changing the design of a contract is in an expensive exercise. If changes in contract designs can be limited to a minimum, the cost of ownership of your SOA will reduce, because calling clients have to change less often.

Do all you can to design service contracts to be binding agnostic

This sounds like a simple point to make, but it's an easy one to forget, and difficult to achieve. The bottom line is that to get the most out WCF from an architect's perspective, you really want to try to ensure that non-functional requirements related to your communication needs do not become hard coded into your contract designs; if you can use configuration to drive transport, policy and encoding decisions, the cost of changing these features later becomes much cheaper than changing code.

This can be hard and at times impossible to achieve. For example, if you decide that you need to use MSMQ integration binding, your service contract will need to use the MsmqMessage<T> class as the only argument allowed in your service operation, and thus your service contract is effectively hard wired to this binding type.

However, with other examples, you can design your contracts in an agnostic way. For example, you may choose to use the Session features of WCF, and could use the IsInitiating and IsTerminating properties of the OperationContractAttrbute in your design to enforce the opening and closing of sessions. Whilst this feature is useful, it will tie you into not being able to use BasicHttpBinding, and thus if you decide later that this binding best suits your communication needs, you will need to change the design of your service contracts accordingly.

Design request data contracts to act as an envelope to service requests

As mentioned above, MsmqIntegration binding requires dedicated service contracts using the MsmqMessage<T> class. If you design a service contract for a web service, but later decide to change this into a service that receives a message from a message queue, you will need to use MsmqMessage<T>, where T is the type of a single data contract.

Consider the following service operation:

int MultiplyNumbers(int firstNumber, int secondNumber);

If you choose to implement this using MsmqIntegration binding, you will need to create an envelope data contract, with properties for the first and second numbers. To avoid having to redesign data contracts later, always wrap multiple arguments into a single request data contract, such as:

int MultiplyNumbers(MultiplicationRequestData request);

Fault contracts require two way communication

Obvious when you think about it, but if you expect service faults to be reported to the calling client, the service operation must use two way communication.

Avoid contract namespace conflicts with the application layer

Be careful how you name you data contracts, because you will normally be wrapping an application with its own API, and this can lead to namespace conflicts which require you to use a fully qualified namespace on every call to the type, which mean messy code. On my project, we have adopted a standard of using EntityNameData as the naming convention for data contracts.

Always assign dates to your schema namespaces

This is important for schema versioning in your contracts, and particularly important in you are planning you use your services with a messaging hub, such as BizTalk Server where subscription is driven off of unique schema namespaces.

Only use types that translate to XSD types in your data contracts

Data contracts should only use types that have a direct comparison in XSD, because you WSDL will otherwise contain XSD import statements to Microsoft generated schemas to represent .Net types. This means using arrays instead of collections, and sticking to enumerations, integers, strings and datatimes.

Do not take an Object Orientated approach

Remember when you are designing a data contract that it is a schema, not an object model. This means that whilst the entities in your application are likely to use inheritance, this approach does not make sense for the generated schema you are creating. Always review your generated schema using svc util to ensure that the contracts create a clean WSDL with clean XSD schemas.

Implement ordering in your data contracts

Ordering is an optional parameter of the DataContractAttribute that controls the order of elements as they appear on the XSD schema that is produced as a result of designing a data contract. If you do not specify order, the schema will be generated in alphabetical order. The affect of this is that newly added elements do not necessarily appear at the end of the schema, which can make altering related artifacts (such as BizTalk maps) more problematic.

Data contracts should define type, not business rules

It is not an in built part of WCF of define validation rules within schema (the data contract), but I am commonly asked how to extend WCF data contracts to validate properties. The reason that WCF does not support XSD restrictions through data contracts out of the box is that implementing business rules through schema design is an expensive way to implement business rules, because if a rule changes, the schema must be changed, and thus calling clients must be made aware of the change. A better way to implement business rules is within the service implementation itself. The data contract should only define the types allowed to be used by the service. This way, changes in business rules do not affect contract designs and services become cheaper to maintain going forward.

Published Sunday, April 22, 2007 10:10 PM by simon.evans
Attachment(s): WCF2.zip

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Philippe Moison said:

Hi Simon,

We have developed an application based on WCF and we have problem to design the best services contracts for our business.

Do you have any business samples based on these WCF Contract Design guidelines ?

June 15, 2007 8:17 AM
 

simon.evans said:

Hi Philippe

These design guidelines are based on my experiences of designing real world WCF contracts over the past 12 months

Unfortunitely, I cannot share specifics on these contracts because the services are protected IP.

If you have specific questions regarding the design of contracts, please leave the questions in the comments and I will do my best to answer them.

June 26, 2007 2:38 PM
 

Prasanna said:

Hi Phillippe

If you are looking for Interoperability then create XSD instead of datacontract and generate data types using XSD.exe or XsdGen, this way you can enforce developers to XSD types instead of dotnet datatypes.

Simon,

Consider the following service operation:

int MultiplyNumbers(int firstNumber, int secondNumber);

instead of using parameters in Operation Contract, i would prefer creating Message Contract and use them, its easy to version

Regards,

Prasanna

lionkrish@gmail.com

January 15, 2008 1:14 PM
 

Hi said:

I have an existing xsd schema and i want to create a data contract class using that xsd schema.

When using the svcutil.exe tool with the following command line option

svcutil /dconly abc.xsd.

It says no code is generated.

Can you tell me what is the most efficient way to create data contract class of existing xsd's.

January 24, 2008 10:29 PM
 

Prasanna said:

svcutil /dconly abc.xsd

To generate data contract class for xsd having attributes and default "form" type, do the following:-

1. XSD should not have attributes defined.

2. All elements should be fully qualified with the namespace.

Ta,

January 29, 2008 11:01 AM
 

Windows Workflow Enhancements in Visual Studio 2008 | PocketPc Reviews said:

March 17, 2008 9:04 AM
 

Smitha R Mangalore said:

Nice Article.

I need your input in defining the service contract for my database service.

I have defined the DBService as service contract with following APIs for writing to database.

public interface IDBService

   {

       [OperationContract]

       int CreateLogEventInfo(LogEventInfo eventInfo);

       [OperationContract]

       void AddLogDataInfo(int id, LogDataInfo dataInfo);

       [OperationContract]

        void AddLogDataInfoList(int id, LogDataInfoList dataInfo);

       [OperationContract]

        void UpdateLogEventInfo(int id, DateTime logStopTime);

       [OperationContract]

        void AddLoggingNotes(int id, string loggingNotes);

       [OperationContract]

       void AddDeviceStatus(int id, string deviceStatus);

   }

All this APIs corresponds to writing different data to database. Now I want to implemet the DB Read APIs. And database may contain huge number of records. So I thought of implementing it using Callback contract.

My Question is

1. Should I need to include DB Read API's like GetAllRecordsByCategory()...and so on... in the same service contract or should I make it as sepearte service like IDBReader{} with callback contract implemented.  I have read in SOA guidelines that "ideal service should not have more than 5 to 6 APIs..If so then rethink on it."

Please guide me on this.

Thanks and Regards

Smitha

August 7, 2008 11:49 AM
 

Khan said:

I am using XSD.exe to generate the datacontract with [XMLSerializableFormat] attribute on the Service Contract interface. When I try to create a test client (console application) and use add servivce reference, in the generated reference class my contract is giving me a message

// CODEGEN: Generating message contract since element name + from namespace + is not marked nillable.

In the XSD, i dont want the element to be nillable it is always required.

Also the contract signature is getting changed in the reference class.

it is changing to

Client.Proxy.methodnameResponse methodname(Client.Proxy.methodnameRequest request);

So the contract signature is getting changed to :

// CODEGEN: Generating message contract since element name + from namespace + is not marked nillable.

Client.Proxy.methodnameResponse methodname(Client.Proxy.methodnameRequest request);

I am passing strongly type and the response is also strongly typed.

Help me .....

why that comment is getting generated

Also why my Operation contract signature is getting changed

August 13, 2008 7:10 PM
 

Joey Powell said:

Hello Simon. I am designing a system using VS2008. I created an asp.net website and then added an interface def and svc file using the WCF service template. In my service I coded several methods, each returning a status and other info. For example a typical method there looks something like this...

     public _RegisterUserServiceCallResult RegisterUser(_UserSession UserSession, _UserAccountInfo UserAccountInfo)

Using this approach I am able to communicate back to the client with status info for both the call and method execution (assuming network timeout for complete fail on communications with service).

Do you agree with this? If not, how would you do it?

Now a bigger question. This one is really important to me. I have read and read and watched screencast after screencast about WCF. I have discovered that WCF is a rapidly-changing area; much of the instructional content uses svcutil.exe and other stuff from VS2005. Little of it seems to support the new way of getting things done with VS2008.

Anyways, I currently have a service contract and some data contracts defined in my interface def, like this...

[ServiceContract]

[DataContract]

Notice I have no "Name", "Namespace" etc information in there. Fact is, I am having a very hard time understanding how to use that. I know that all of my stuff works without any "Namespace" info. But I can imagine things are not going to be pretty when I want to try to change something after I have already deployed clients.

I want to understand how to use versioning and namespaces. I also want to be able to put the config info (service endpoing connections, etc...) into code within the client app, instead of in an app.config file. This would allow for building in a simple config dialog and allowing for the client to be more receptive to changes in the future.

Can you please point me to any simple info on how to do stuff like this?

Also, if you have any links or advice for me, I would sincerely appreciate it.

Thanks,

JP

joey.powell@[REMOVE]topscene.com

September 29, 2008 9:25 PM
 

Daniel Bryars said:

"Design request data contracts to act as an envelope to service requests"

I came accross this post whilst investigating a way to allow backward compatible changes to our operation contracts.

For example:

[OperationContract]

void UpdatePhoneDetails(Int32 phoneId, Int32 a, Int32 b)

then sometime later I want to add a parameter c, like this:

[OperationContract]

void UpdatePhoneDetails(Int32 phoneId, Int32 a, Int32 b, String c)

But I want to want the existing clients to continue to "just" work the same way, I don't see the value and I don't want the overhead of changing the namespace of the API.

So now I'm considering using:

void UpdatePhoneDetails(UpdatePhoneDetails_RequestData request);

allowing me to add DataMembers to my heart's content and specify a default value.

Is this a good idea? Am I going to regret this design in future? Would and why might an explicitly versioned (by date as you recommend) namespace be better?

Taking the idea further, I'd wrap the return type in a Response message; the example in your post:

int MultiplyNumbers(MultiplicationRequestData request);

would change to:

MultiplicationResponseData MultiplyNumbers(MultiplicationRequestData request);

That way I can return "more stuff" whilst keeping the exisiting clients from breaking.

What do you think?

Many thanks,

Daniel

May 13, 2009 8:19 PM
 

Neoteny said:

Sounds interesting that you give such idea.. Well thanks, its a great help... It was my first time here in this site... That is why it calls my attention to visit it again for more source of new information.. Great article..

November 8, 2010 7:49 AM
 

Service Design said:

This site is really interesting. You bring up some great points about your article... .. Thanks for the great information.. It is my first time here in this site... That is why it calls my attention to visit it again for more source of new information.. Great article..

December 2, 2010 2:36 AM
 

Website Design Service said:

Our team of professional web designers offer the best <a href="http://www.mapitinc.com/basic-website-design.php">website design service</a>. The responsibility of our web design company is not to design a website only, but to design an online face for our customers that reflect their vision, mission, and strategy.

October 14, 2013 7:59 AM

Leave a Comment

(required) 
(optional)
(required) 
Submit

About simon.evans

Simon is a Managing Consultant for Conchango in the UK, part of EMC Consulting Services. He is an expert in .NET development, and more specifically in WCF and ASP.NET, having participated in several Microsoft early adoption programs. Simon believes deeply that a broad understanding of key technology concepts is an essential foundation to being a gifted designer and builder of solutions.
Powered by Community Server (Personal Edition), by Telligent Systems