Two WSDLs, Same Definition, Different Endpoints


We are consuming an external WSDL in our app layer using a Service Reference.  Its actually the PayPal WSDL.

They have a test (sandbox) WSDL url and a live production WSDL url.  They both have the same definition but with different wsdl locations and different endpoints.  So how does one handle this in their code?  

We are basically trying to figure out how we can eliminate duplicate clasess/methods but be able to easily run the code for either the sanbox or live site using some config app keys or something.  Not sure what that all entails.

Do I need both of them as Service References?  If so, we can't include both in the same class file, otherwise there is ambiguity, so then do we need different classes and methods for each WSDL service reference?  

Is there a way to only use the live WSDL as the service reference but pass in the sandbox endpoint url so it hits their test site?  Is there anything else needed to be able to do this?

Ideas?  Thanks, ks

Who is Participating?
käµfm³d 👽Commented:
Part of you confusion may stem from the use of the term "reference". There is not an actual reference (like you would have in a Forms project); rather there is a conversion of the WSDL into a class or set of classes which can inter-operate with the service. Web services are designed to be architecture and language independent, so the internal storage of data should be irrelevant. What I was trying to imply above is that the "data type" the service cares about at its exposed point is that described by the XML (e.g. xs:string, xs:int, etc)--it doesn't know if you store it internally as an int, string, Point, Rectangle, etc. Just as you store your data in some class(es), the backend of the service stores its data in a structure familiar to it.

In short what I am saying is that if the XML types and namespaces are the same for both services, and that your internal storage (which should have been generated for you when you added a service reference to the WSDL) can safely be converted to those types (which it should since .NET did the class creation for you), then I don't see a reason why you would need a reference to both services. You should be able to use the same classes for each service and just change the endpoint as necessary.
käµfm³d 👽Commented:
>>  Do I need both of them as Service References?  If so, we can't include both in the same class file, otherwise there is ambiguity, so then do we need different classes and methods for each WSDL service reference?  

The wonderful thing about "Add Service Reference," though, is that at the bottom of the dialog, you can specify the namespace you would like to give to the reference being added (see screenshot). So you can potentially add both references, but give them different and meaningful namespaces, and there should be no conflict.
kruegersteAuthor Commented:
That part I do understand and they do have different namespaces but that leads me to the other questions I had.  Are you able to answer any of the other ones?  

How do I differentiate between the two services in my code?  They have the same exact definition but different endpoints.

If they have different definitions, do I still need both even if they can have different namespaces?  If I have to reference both, then even with different namespaces, when I do the following, ambiguity persists:

using PayPalSvc;
using PayPalSvcSandbox;

We really need help with the overall solution of how to handle two services with the exact same definition but different endpoints.  Is it only the endpoint that matters if they are the same but different locations?  

Please help :)
Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

kruegersteAuthor Commented:
Below is my method for doing the direct payment.  

So how do I specify an endpoint here?  Is this suppose to be in my web.config?  When I created the service, it created an app.config file with some endpoints and stuff in the c# class library.  But obviously my web app can't see that app.config.

And then the other issue of trying to use the same method/class for both the sandbox and live references.   Again, are they both really needed?  if so, how do i handle this?  if not, how do i handle this?
using System;
using System.Data;
using PayPalSvcSandbox;
using PayPalSvc;

public class PaymentBL
  public String DoDirectPayment(MOPInfo creditCardMOPInfo, String ipAddress)
                PayPalAPIAAInterfaceClient client = new PayPalAPIAAInterfaceClient();
                CustomSecurityHeaderType credentials = new CustomSecurityHeaderType();
                credentials.Credentials = new UserIdPasswordType();
                credentials.Credentials.Username = SecurityBL.Decrypt(ConfigurationUtil.PayPalAPIUsername);
                credentials.Credentials.Password = SecurityBL.Decrypt(ConfigurationUtil.PayPalAPIPassword);
                credentials.Credentials.Signature = SecurityBL.Decrypt(ConfigurationUtil.PayPalAPISignature);
                credentials.Credentials.DevId = ConfigurationUtil.PayPalAPIEnvironment;
                DoDirectPaymentReq request = new DoDirectPaymentReq();
                request.DoDirectPaymentRequest = new DoDirectPaymentRequestType();
                request.DoDirectPaymentRequest.Version = "51.0";

                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails = new DoDirectPaymentRequestDetailsType();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.IPAddress = ipAddress;

                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard = new CreditCardDetailsType();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CreditCardNumber = creditCardMOPInfo.CreditCardNumber;
                switch (creditCardMOPInfo.CreditCardType)
				    case ConstantRepository.CREDIT_CARD_VISA:
					    request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Visa;
				    case ConstantRepository.CREDIT_CARD_MASTERCARD:
					    request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.MasterCard;
				    case ConstantRepository.CREDIT_CARD_DISCOVER:
					    request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Discover;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.ExpMonth = creditCardMOPInfo.CreditCardExpMonth.ToInt32();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.ExpMonthSpecified = true;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.ExpYear = creditCardMOPInfo.CreditCardExpYear.ToInt32();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.ExpYearSpecified = true;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CVV2 = creditCardMOPInfo.CreditCardSecurityCode;

                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner = new PayerInfoType();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Payer = "";
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerStatus = PayPalUserStatusCodeType.unverified;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerCountry = CountryCodeType.US;

                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName = new PersonNameType();      
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName.FirstName = CustomerBL.GetName(creditCardMOPInfo.CreditCardName, EnumRepository.NamePart.FirstName);
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.PayerName.LastName = CustomerBL.GetName(creditCardMOPInfo.CreditCardName, EnumRepository.NamePart.LastName);
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address = new AddressType();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Street1 = creditCardMOPInfo.MOPAddress.AddressLine1;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Street2 = creditCardMOPInfo.MOPAddress.AddressLine2;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CityName = creditCardMOPInfo.MOPAddress.City;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.StateOrProvince = creditCardMOPInfo.MOPAddress.StateCode;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.PostalCode = creditCardMOPInfo.MOPAddress.ZipCode.ToString();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CountryName = "USA";
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.Country = CountryCodeType.US;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CardOwner.Address.CountrySpecified = true;

                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.PaymentDetails = new PaymentDetailsType();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal = new BasicAmountType();
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal.currencyID = CurrencyCodeType.USD;
                request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.PaymentDetails.OrderTotal.Value = creditCardMOPInfo.MOPAmount.ToString();

                var response = client.DoDirectPayment(ref credentials, request);

			    return response.ToString();

Open in new window

käµfm³d 👽Commented:
Line 12 should have an overload that allows you to pass in the name of the configuration (as specified in your web.config/app.config).
kruegersteAuthor Commented:
So does this mean I don't need both services referenced if they have the same definition?  And I can just pass in a different endpoint name, depending on the location/environment to hit?
käµfm³d 👽Commented:
I believe that as long as the namespaces on the XML itself are the same, then it should be possible. I haven't personally dealt with a scenario like this, though, so I can only surmise.
kruegersteAuthor Commented:
Anybody else?
käµfm³d 👽Commented:
If they have different definitions, do I still need both even if they can have different namespaces?  If I have to reference both, then even with different namespaces, when I do the following, ambiguity persists:

using PayPalSvc;
using PayPalSvcSandbox;

Of course there is ambiguity. You have included both namespaces in your "using" section. How would C# know which class you are referring to? If you want to stick with having a reference to both services, then you can provide another "using" in the context of an alias:

    using TestSvc = PayPalSvcSandbox.PaymentBL;

Then in code, you can refer to TestSvc.DoDirectPayment() rather than its official name.
kruegersteAuthor Commented:
It isn't so much "do I want to have both references", my question was, do I need both WSDL references?  I'm trying to first understand the correct solution, I haven't picked one cause I'm not sure which way to go.  This can't be that extraordinary of an issue.  I would assume many 3rd parties have this sort of architecture.  

I think my preference would to not use both in order to prevent having redundant code.  But again, I don't know what issues this would cause, if any.  I guess maybe this part is a PayPal question and I am waiting for a response from them.  They do have versioning too that is specified in the call so you would think that is even more of a reason you could get away with using one WSDL definition and different endpoints, no?

If it turns out that both references are definitely needed, then I will revisit your last post on how to handle this.  It seems your example is for placement in the calling method that is using the DoDirectPayment() method.  But my issue is actually inside the PaymentBL class on how to implement a class and methods using both references.  
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.