Ferhat
Ferhat

Reputation: 63

Using DLL references of WCF service in another WCF service

Sorry for the long question in the first place. I would rather prefer to come up with a shorter question but this is the most stripped version I could provide that I can clearly explain my point.

I have been trying to deliver a wrapper service to our client which should provide multiple services in it. Idea behind it is to reduce multiple calls to a one call and return a single object which has other associated objects in it. To illustrate my point, let me give following example:

Let's say we have following services:

Normally client should query Donation service (with a donationID) to get donation information, and then using the retrieved donation information, they should query Payment service to get payment related details, and if the payment is done in multiple small payments, using retrieved payment information, they should query PartialPayment service to get all donation information for a particular Donor.

Instead of client doing this, I am going to provide a wrapper service to accept donationID as a single parameter and return a class similar to this:

[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class DonationDetail
{
     [DataMember]
     public MyCompany.Services.Donation.Record donationRecord;
     [DataMember]
     public PaymentDetail paymentDetail;    
}

[DataContract(Namespace = "http://MyCompany.Services.DonationDetail")]
public class PaymentDetail
{
     [DataMember]
     public MyCompany.Services.Payment.Record paymentRecord;
     [DataMember]
     public List<MyCompany.Services.PartialPayment.Record> partialPayments;
}

So an instance of DonationDetail record should return all relevant information with that donation.

My problem arises when I use these individual services DLL's* in my wrapper service since any class I pass to client using wrapper service becomes part of the wrapper service and client can't use them right away with the corresponding types they retrieved using service references without writing a custom construction method to convert one type to another - although they are same objects. Instead of referring classes in original namespace, service uses following classes something like that now for the classes mentioned above:

Is there a way to provide such an interface without a custom constructor? So, if they use "PartialPayment" namespace for the MyCompany.Services.PartialPayment WCF service, can they do something below after DonationDetail is retrieved via wrapper service?

PartialPayment.Record partialPayment = dDetailObj.paymentDetail.partialPayments[0];

*: Don't ask me why I don't use service references unless that is the cause of the problem, since that option gives me other problems to me at this point)

Upvotes: 0

Views: 2198

Answers (1)

kmp
kmp

Reputation: 10865

So I think what you are saying, effectively, is that if you have two different services that return the same object and when you add this as two different service references to the client, even though ultimately they are the same object as far as the services are concerned (since they reference the same DLL), the client sees them as two different types so you can't take the object returned from one and send it as the input to the other service.

Assuming I have understood your question (and I apologise if I have not)...

You could map one type to the other by constructing it and setting the properties but that is really kind of a pain and not very friendly to the consumer etc, hence I am going to suggest something kind of radical...

Ditch the service references on the client.

Yup, I said it, why would I suggest such a thing!?! Here's why...

First of all I would make sure my project was structured something like this:

Donation Detail Client Library

  • IDonationService (this is the service contract - notice no implementation in the client library)
  • DonationRecord

Payment Detail Client Library

  • IPaymentService (this is the service contract - notice no implementation in the client library)
  • PaymentRecord

Partial Payment Client Library

  • IPartialPaymentService (this is the service contract - notice no implementation in the client library)
  • PartialPaymentRecord

Wrapper Service Client Library (which references the three other client libraries)

  • IWrapperService (this is the service contract - notice no implementation in the client library)

Incidentally, I gave your records different class names but you could use namespaces if you like and call them all Record (I think calling them different names is less confusing, but that is probably just me).

On the service end you reference the client library that you need to implement the service and do whatever you have to do just as you always have.

On the client you reference the client libary (or libraries depending on what service you want to call) too, in the same way (so you effectively have a shared library between server and client - yeah old skool, but hey, you will see why).

The client then has the interface for the service contract and all the data contracts so it does not need the whole service reference, generated code thing. Instead what you can do on your client is something like this:

DonationRecord donation;

using (var cf = new ChannelFactory<IDonationService>("EndpointNameInConfigurationFile"))
{
    IDonationService donationservice = cf.CreateChannel();
    donation = donationservice.GetDonation("Donation1234");
}

using (var cf = new ChannelFactory<IWrapperService>("EndpointNameInConfigurationFile"))
{
    IWrapperService wrapperService = cf.CreateChannel();
    wrapperService.DoSomethingWithDonation(donation);
}

There, you see I took the data contract from one service and sent it to a completely unrelated service and it looks natural (I have an object that is returned from a method on class X and I took it and passed it as an agrument on class Y, job done, just like programming).

NOTE: Using this technique will not stop service references from working just as they always have so any existing client code would not have to change, just if you use your new wrapper service, you could use it like this to save having to map types.

Upvotes: 2

Related Questions