8

I'm consuming a SOAP web service. The web service designates a separate service URL for each of its customers. I don't know why they do that. All their functions and parameters are technically the same. But if I want to write a program for the service I have to know for each company is it intended. That means for a company called "apple" i have to use the following using statement:

using DMDelivery.apple;

and for the other called "orange"

using DMDelivery.orange;

But I would like to my program to work for all of them and have the name of the company or the service reference point as a parameter.

Update: If I have to write a separate application for each customer then I would have to keep all of them updated with each other with every small change and that would be one heck of an inefficient job as the number of customers increase.

Can anyone think of a solution? I'll be grateful.

disasterkid
  • 6,948
  • 25
  • 94
  • 179
  • I guess you are currently adding the web service reference using "Add Service Reference", am I right? – Ranhiru Jude Cooray May 06 '13 at 07:32
  • 1
    I think you might want to use an Adapter pattern, or some other design pattern out there (Facade also comes to mind). – Lews Therin May 06 '13 at 07:33
  • what is inside each namespace ? model + contract ? event if DMDelivery.apple.MyFunction and DMDelivery.orange.MyFunction seems to be the same method, it' not the same in fact. it's a bit more complicated. – Cybermaxs May 06 '13 at 07:36
  • Take a look at dynamic web service consumption/invoke/invocation. This [codeproject article](http://www.codeproject.com/Articles/376168/Csharp-Dynamic-Web-Service-Invoker) might come in handy. – Ranhiru Jude Cooray May 06 '13 at 07:37
  • @RanhiruCooray yes I am using the "Add Service Reference". – disasterkid May 06 '13 at 07:41
  • @Cybermaxs inside each namespace lies the model. Yes they will not be the same function I know. That's why I'm asking this questions. – disasterkid May 06 '13 at 07:45
  • I added an update to the question explaining the problem: "If I have to write a separate application for each customer then I would have to keep all of them updated with each other with every small change and that would be one heck of an inefficient job as the number of customers increase." – disasterkid May 06 '13 at 07:52

3 Answers3

3

If you have a base contract (interface) for all your services you can use a kind of factory to instantiate your concrete service and only have a reference to your interface in your client code (calling code).

//service interface
public interface IFruitService{
  void SomeOperation();
}

//apple service
public class AppleService : IFruitService{
  public void SomeOperation(){
    //implementation
  }
}

Having for example a kind of factory class (you can put your using statements here)

public static class ServiceFactory{
  public static IFruitService CreateService(string kind){
    if(kind == "apple")
      return new AppleService();
    else if(kind == "orange")
      return new OrangeService();
    else
      return null;
  }
}

And in your calling code (you just add an using statement for the namespace containing your interface):

string fruitKind = //get it from configuration
IFruitService service = ServiceFactory.CreateService( fruitKind );
service.SomeOperation();

You can also use the Dependency Injection principle.

Community
  • 1
  • 1
polkduran
  • 2,533
  • 24
  • 34
  • does this mean I should have a separate implementation of the service for each customer (one for Apple and one for Orange) while almost all their functions are the same? That will double the size of my code. – disasterkid May 06 '13 at 10:22
  • 1
    No, what I try to show is that each service has its own implementation and as you say "almost all their functions are the same", then you can create an interface (or a base class) that "hides" the implementation to the calling code. In this case, your calling code does not know if it is working with an "apple" or an "orange" service, it only knows that it is working with an implementation of a `IFruitService` interface (or a commun base class). This way you only write **once** the code for you client (calling code). – polkduran May 06 '13 at 10:31
  • that sounds reasonable. and the instance of the service to call (whether apple or orange) will be an input parameter right? – disasterkid May 06 '13 at 10:39
  • 1
    Right. Then it is up to you (and depending on your system) how you retrieve the "kind" of service to use: by configuration, a parameter to a method or a class... – polkduran May 06 '13 at 10:51
0

If everything is the same and it's only the endpoint address that is different, maybe you can try changing only that before invoking the web service methods.

MyWebServiceObject ws= new MyWebServiceObject();
ws.Endpoint.Address = new System.ServiceModel.EndpointAddress("http://www.blah.com/apple.asmx");
Ranhiru Jude Cooray
  • 19,542
  • 20
  • 83
  • 128
  • I have many classes in my program. What should I do with all those "using" statements? Is there a way to globally announce a using statement that applies to all those classes? Like "Add User Import" in VB.Net. – disasterkid May 06 '13 at 08:15
0
  1. Use any one client in your implementation. ex. Apple
  2. Write a message inspector and attach this into the out going point
  3. In message inspector replace the name space of the type with appropriate client name space. EX: Before Message inspector :MyClinet.Apple.Type
    After Message Inspector : MyClient.Orange.Type, if the Provider is Orange.
Senthil Kumar NH
  • 431
  • 1
  • 5
  • 13