views:

321

answers:

4

I am working on a WCF application with a server and a client (naturally). In server project, I defined the classes with contract attributes.

Now when the server is ready, I added the service reference and it created the proxy for me. I used it and it did work fine.

The question I want to ask is, is it OK if I create a common DLL which contains the class definitions with contract attributes and use it for both server and client (instead of using the classes generated for client by Visual Studio). If I use common classes, I don't have to worry about generics collections being converted into arrays while automatic code generation. Is it silly? Is it possible? Have anyone done this before? Is it OK to do this?

The deployment scenario is such that there will be limited (few) number of clients in a secure intranet and it is OK to update existing clients whenever there is a change in server.

+1  A: 

That approach is fine (I use that quite a bit) as long as you control the client. It won't work (obviously) with java clients etc. If you know you will never need to support non-.NET clients, then it can be powerful, but it breaks some purist SOA rules. In particular, yes, an intranet scenario is one where I might consider this approach.

Both svcutil.exe and the IDE have options to re-use types from existing assemblies to do exactly this.

edit another advantage of this approach is if you want to use the same validation logic at the client, without coding it twice - for example IDataErrorInfo etc.

Marc Gravell
+2  A: 

If your only concern is not having collections turned into arrays, you don't have to go this far. The Advanced button on the Add Service Reference dialog allows you to specify what type to use for cases like this. You can have it use List instead of T[].

John Saunders
Its not just that. Its updating the service reference whenever there is a change in these classes. And it also feels more comfortable when less code is generated by IDE.I just wanted to ensure that if I follow this approach, I am not doing something taboo or horribly against standard/guidelines.
Hemant
Well, you don't have to update the service references whenever you make a change - only when you change the contract. I hope you don't do that very often.You could also consider using the Service Factory (http://www.codeplex.com/servicefactory). It would update client and service together.
John Saunders
+2  A: 

Maintaining contract types in a separate, common assembly is a really good idea. It gives you the chance to add Adapters, for example, to convert between the contract types and other business objects you may have, or Mediators, etc, between those types.

It makes sense to use common types even if you do not control all clients. Suppose you have a service that is consumed by internal apps that use .NET, and also by trusted third parties at a partner company. The partner apps use Java, or Ruby, or Python. In this case the partner won't have access to the shared types, but relying on the WSD/XSD, can roll their own client-side type library. That should not preclude you from providing a nice package of shared types to your in-house devs.

This recommendation to share types also applies when you use a REST interface as opposed to WS/SOAP. With REST, WSDL is lacking but XSD (or similar) would still be used to describe the types of the messages that the server and its clients exchange. So no change in advise regardless of whether you use SOAP or REST.

EDIT: And, it applies whether you use .NET or Java or anything else. If you control both ends of the wire and the platforms are the same, then yes, you should share types. Why wouldn't you?

Cheeso
+1  A: 

Once you've created separate assemblies to hold contracts you can reference these assemblies and use them to create channels (using ChannelFactory) to the service from the client. By doing this you're no longer required to update the 'service reference' every time you change a service contract.

ChannelFactory<IContract> factory = 
    new ChannelFactory<IContract>("endpointName");
David Walschots