tags:

views:

1071

answers:

4

Hi,

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

+3  A: 

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.

Andrew Hare
In addition, when you add the service reference, you want to use the Advanced tab to specify which types should be shared.
John Saunders
Hiya, the problem with combining the two services is that they are eventually going to become massive. I've read in Jual Lowrys book that you should strive to have no more that 12 members of the service contract?
Simian
@Stuart - I would not recommend combining services simply for this reason. I trust that your services are separated purposefully so mushing them together doesn't always make sense. I just wanted to make sure you were aware of every option.
Andrew Hare
Andrew, you're correct, the services are defined in a meaningful way so to combine them together simply to achive my aims stated in the question would not really make sense. In addition I don't really won't to reference the data contract on the client - the datacontract references my business object assembly, something I don't want the client to have to reference - due to the fact the client already has a definition of objects from the service and I don't want a clash of namespaces from the assembly and from the service. I'm stil unsure of how to proceed with this one. Thanks.
Simian
I agree with Andrew, there should be a separate assembly (or tree of assemblies) that contain nothing but service contracts and data contracts - no code. That way, your service design won't be constrained by dependency issues.
Christian Hayter
A: 

Hi,

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

Simian
A: 

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.

Christian Hayter
I do want them to be semantically equal, as in the domain the Device.Customer and User.Customer are the same entity. The code for the service definition and the contracts are in the same assembly, what I was try to say is that how I can expose these services as a single service, and it seems the answer is use multiple endpoints on the same service.
Simian
+1  A: 

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.

Darin Dimitrov