Solved

Two WSDLs, Same Definition, Different Endpoints

Posted on 2011-02-24
10
1,241 Views
Last Modified: 2012-05-11
Hello,

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

0
Comment
Question by:kruegerste
  • 5
  • 5
10 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
>>  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.
untitled.PNG
0
 
LVL 4

Author Comment

by:kruegerste
Comment Utility
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 :)
0
 
LVL 4

Author Comment

by:kruegerste
Comment Utility
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)
		{
            try
            {
                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;
					    break;
				    case ConstantRepository.CREDIT_CARD_MASTERCARD:
					    request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.MasterCard;
					    break;
				    case ConstantRepository.CREDIT_CARD_DISCOVER:
					    request.DoDirectPaymentRequest.DoDirectPaymentRequestDetails.CreditCard.CreditCardType = CreditCardTypeType.Discover;
					    break;
			    }
                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

0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
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).
0
 
LVL 4

Author Comment

by:kruegerste
Comment Utility
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?
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
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.
0
 
LVL 4

Author Comment

by:kruegerste
Comment Utility
Anybody else?
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
Comment Utility
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.
0
 
LVL 4

Author Comment

by:kruegerste
Comment Utility
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.  
0
 
LVL 74

Accepted Solution

by:
käµfm³d   👽 earned 500 total points
Comment Utility
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.
0

Featured Post

Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

While working on Silverlight and WCF application, I faced one issue where fault exception occurred at WCF operation contract is not getting propagated to Silverlight client. So after searching net I came to know that it was behavior by default for s…
Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now