For example I have two services hosted in IIS.
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
DeviceCollection GetAllDevices(Customer customer);
}
[ServiceContract]
public interface IUserService
{
[OperationContract]
User Authenticate(string username, string password);
}
Both the User object that is returned from the Authenticate operation in the UserService and the DeviceCollection that is returned from the GetAllDevices operation in the DeviceService have a child object definition of Customer. Customer is a business object is in the same assembly as the User and Device objects.
My problem is on the client - when I call the device operation
userProxy.GetAllDevices(user.Customer);
The compiler complains with the following message:
Argument 1 - Cannot convert from UserService.Customer to DeviceService.Customer
I can connect to both services fine, it's the object definition of Customer that is the problem. I don't really want to put the Operations in the same service as they seem to live naturally in their own services. I guess what I'm asking is that how to other programmers deal with such a problem?
Cheers,
Stuart
If you want to share a data contract across multiple services then you will have to compile the data contract in question into its own assembly and then distribute that assembly to the client.
Even though the type appears to be the same, it is in fact a two separate types and that is why you are seeing the error that you are seeing. Your only other choice (other than a separate, shared assembly) is to combine the two services into one so that they can share the data contract.
One option would be to use AutoMapper on the client to convert seamlessly from one type to another. As they have the same properties mappings would be straightforward.
It's a semantic issue. If you want to define one UserService.Customer and DeviceService.Customer as semantically equal, then you ought to physically re-factor that data contract into a separate assembly. Alternatively, if you want to define UserService.Customer and DeviceService.Customer as semantically different, then keep them as separate types and write a utility function to translate from one to the other.
I thought I'd attempt to answer my own question with details on how I'd over come this solution. It was based on an article on a blog article by Dan Meineck.
Is summary, I think my concept of having multiple services for each of my root business entities was misguided.
Instead I exposed a single service which implemented several DataContracts eg
public partial class DeviceService : IDeviceService, IUserService
{
}
Because device service is created as a partial class this allowed me to separate the services, well I say separate, they are still the same service but it allowed me to separate them into separate files and give some structural organisation to the service.
The last piece of the implementation was to declare two end points in the service definition eg
<service behaviorConfiguration="GPSCloudHost.DeviceServiceBehavior" name="BusinessService.DeviceService">
<endpoint address="Device" binding="wsHttpBinding" contract="BusinessService.DataContracts.IDeviceService"></endpoint>
<endpoint address="User" binding="wsHttpBinding" contract="BusinessService.DataContracts.IUserService"></endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
I'm not experienced in WCF enought to say if this is "correct" solution or not, but it's working a treat for my requirements. If anyone else has a better solution I'd love to hear it!
Cheers