views:

855

answers:

5

Hi, I have a complex data type, including a number of functions, as well as the usual get and get methods. My life would be considerably easier if I could use WCF so my client can also use this data type.

Do I

  1. Ignore all the operations, putting [DataMemeber] only where needed.

  2. Put the class in question in a shared library assembly for both client and server to access.

Thanks, Roberto

PS. I realise that the question is probably not as well worded as it could be.

+2  A: 

All that's transferred across the WCF boundary is what is serialized - which amounts to the class's state. The methods won't be. So if you need them to be available both sides, then you'll need a shared library as you suggest.

When you add a service reference, you have the option to reuse the data type, in which case WCF will deserialize into the shared class, complete with methods. But it's only the field values that have actually been transferred across the boundary.

David M
I'm assuming that this would be in the "Configure Service Reference" dialog ?? Its set to reuse types in all referenced assemblies. Is this correct??
Roberto Bonini
Yes, that's the one.
David M
A: 

Short answer: yes. WCF handles complex types like a champ. When passing your complex type you want to focus just on the data being passed. If your client does not share a DLL, it becomes even more important to focus just on the data being passed (and not any additional operations) because the client will only get a copy of the complex type's data members.

I'm guessing you come from a Java background? With WCF you will need to either mark the fields with DataMember attributes or (better yet) change your get/set methods to properties.

For example, instead of:

[DataContract]
public class Foo
{
   [DataMember]
   private string bar;

   public string GetBar()
   {
      return bar;
   }

   public void SetBar(string b)
   {
      bar = b;
   }
}

You could use the following:

[DataContract]
public class Foo
{
   [DataMember]
   public string Bar { get; set; }
}
AgileJon
A: 

The best practice for a Data Contract is for it to be a contract - data only with no behavior. The second best practice would be for you to decorate your class with [DataMember], and to keep it on the server - let the client use the proxy copy.

John Saunders
+1  A: 

Ok, it turns out to be a combination of all the above answers.

  1. Stick the data classes into a shared assembly, referenced from both the client and server projects.
  2. Make sure you have the "Reuse Types in Referenced Assemblies" item checked in the "Configure Service Reference" dialog.
  3. At the begining of each of your data contracts put a [KnownType] attribute.

The code looks like so:

[DataContract]
[KnownType(typeof(WHS2SmugmugShared.Photo))]
[KnownType(typeof(WHS2SmugmugShared.PhotoInfo))]
public class Photo
{
//code here
}

In the above case, I use PhotoInfo in the Photo class. PhotoInfo does NOT have a KnownType attribute associated with it in the class file. And it does not appear to be required.

This allows you to serialize complex types but still keep their operations.

Roberto Bonini
A: 

Decorate All such types with serializable attribute.So, you dont need to place [DataContract] attribute for each complex class participating in your WCF service.

Add the dll containing thoes types at WCF client and let proxy reuse those classes instead of regenerating those required for deserilization. And if any types is added intoproxy delete it and use from dll. This way I easily shared my complex types accross services. But it is only applicable if you can shrae your types as seperate dll.

Izhar