WCF - multiple service contracts using the same data

I have a new question for the WCF guru.

So, I have a User class that is close to the "User" view from the database, which I use for database operations. Now I would like to have 2 different service contracts that use this class as a data contract, but each in its own way ... I mean

 public class DBLayer { void InsertUsers(List<User> userList) { // both 'PropertyVisibleForService1' and 'PropertyVisibleForService2' // are used HERE to be inserted into their columns } } [DataContract] public class User { [DataMember] public string PropertyVisibleOnlyForService1{...} [DataMember] public string PropertyVisibleOnlyForService2{...} } [ServiceContract] public interface IService1 { List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside } [ServiceContract] public interface IService2 { List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside } 

So the idea is that each service will get a different user, a subset of 'User' . Bearing in mind that I want to use 'User' as for database operations, what would be my options for achieving this? Do I really need to create different data contracts or is there another smarter way?

It would be best not only to give me a solution, but also to explain to me some best practices and alternatives.

Thanks in advance.

EDIT1: I added a dummy DBLayer class for a better overview and why I think inheritance might not be very good in this case.

The solution will have other " UserForService1 " and " UserForService2 " as data contracts, which will be displayed at the end from / to " User ", but I need other points of view.

EDIT2: A very good article that helped me in this case: http://bloggingabout.net/blogs/vagif/archive/2009/03/29/iextensibledataobject-is-not-only-for-backward-compatibility.aspx

+7
source share
4 answers

You can create a separate DTO for each service, but your case is really perfect for a drawing decorator :

 [DataContract] public class UserForService1 : User { private User mUser; public UserForService1(User u) { mUser = u; } //expose only properties you'd like the user of this data contract to see [DataMember] public string SomeProperty { get { //always call into the 'wrapped' object return mUser.SomeProperty; } set { mUser.SomeProperty = value; } } // etc... } 

and for Service2 is similar code that provides only what you need ...

+4
source

If they are intended to represent different types of users, they should be different classes. I agree with phoog in the comments, you should get the type you want from the generic User class and add specific service properties to the derived classes.

Why don't you think the legacy would be good in this case? If you give us more detailed information, we can try to revise the proposals in accordance with your actual problems.

+1
source

As stated in the commentary, you can have two classes based on the base user, then using the "Known data types" , you can accomplish the desired Goal. See the following links for more examples.

http://www.freddes.se/2010/05/19/wcf-knowntype-attribute-example/

http://footheory.com/blogs/bennie/archive/2007/07/28/handling-data-contract-object-hierarchies-in-wcf.aspx

+1
source

If you do not want to use inheritance, for example:

 [DataContract] public class User { } [DataContract] public class Service1User : User { [DataMember] public string PropertyVisibleOnlyForService1{...} } [DataContract] public class Service2User : User { [DataMember] public string PropertyVisibleOnlyForService2{...} } [ServiceContract] public interface IService1 { List<Service1User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside } [ServiceContract] public interface IService2 { List<Service2User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside } 

Then I'm not sure what you will do. Your sortof breaks down the principles of type declaration at this point. Think about it in normal .NET mode; if you define "User" in your application, then it is the same everywhere. Some properties cannot be hidden from some other classes or methods.

WCF is also going to pack this type of information into the generated WSDL, and it will only determine the user type once, so it needs to know what properties exist.

Now, if all you care about is the actual SOAP message that was designed, and you don't care about the WSDL or what any clients created from WSDL will see, then technically you can make it not highlight it property in the SOAP message when it is null by doing:

  [DataMember(EmitDefaultValue=false)] 

Then, when this property is null, it will not be included in serialization. This would not make any difference if the client were created from WSDL, although its user type should still contain both properties. This will simply change the serialization so that instead of sending to the client something like:

 <User> <PropertyVisibleOnlyForService1 nil="true" /> <PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2> </User> 

instead, it will send:

 <User> <PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2> </User> 
+1
source

All Articles