views:

871

answers:

3

This relates specifically to .NET. And I've decided to use the Web service Reference instead of Web Service...I think though my questions below really are for either situation and I want to try to get the overall idea of this.

So here is the issue for me. Let me first explain where I'm coming from. One past projects, I've talked to a couple APIs before by creating manual classes such as a GetPicturesRequest.cs and a GetPicturesResponse.cs for example that would hold state for me. I'd have a base class called Request.cs that did the actual sending of the api call:

        Stream requestStream;
        Stream responseStream;
        XmlDocument doc = new XmlDocument();
        doc = CreateRequestXML();

        // Determins if API call needs to use a session based URI
        string requestURI = UseAuthURI == true ? _requestURIAuthBased + JSessionID : _requestURI;

        byte[] data = XmlUtil.DocumentToBytes(doc);

        // Create the atual Request instance
        HttpWebRequest request = CreateWebRequest(requestURI, data.Length);
        request.ContentLength = data.Length;
        request.KeepAlive = false;
        request.Timeout = 30000;

        // Send the Request
        requestStream = request.GetRequestStream();
        requestStream.Write(data, 0, data.Length);
        requestStream.Close();

ok, but now I want to use a Web service Reference. So I pointed and created a new reference to https://www.sandbox.paypal.com/wsdl/PayPalSvc.wsdl in VS 2008. I now have a Web Reference.

I have now these questions as being a first time user of web services as opposed to doing things manually as I was to use a 3rd party API:

1) How can I specify header params? For instance some APIs require you to send a hash (signature), sessionID, username, password, you name it along with the API method call request. How do you specify this using a web service proxy class?

2) How is the request/response objects handled or do I not need to worry about this now that I'm using a web service/reference? I mean do I need to create a request object still and how would I receive the response?

3) When I receive the response, does the PRoxy class contain its state or do I have to still create a class to hold the state of the returned data from the API method call response when using web services/references?

4) When ever would I want to instead just create custom code like I did before and not use web services/reference option with WSDL?...essentially creating my own proxy classes, request objects, response objects, everything? Rather than have VS spit out a Web Reference based on a WSDL? Is it because if it's not a SOAP based 3rd party API? Is it because the 3rd party API does not provide a WSDL then you're forced to hand code the wrappers yourself?

thanks.

A: 

1) In your case signature, username and password are transferred in a soap header. You will need to install WSE 3.0, activate it in your VS project and generate proxy once again.

2) Request creation and response parsing are made by WSE internals. Just create proxy, set the header and call the method on proxy.

3) There should be very strong reason to create custom implementation of proxy. WSE covers SOAP scenarios and part of WS-* specifications. WCF covers TCP, Pipes and MSMQ transports in addition to SOAP. Even if service doesn't provide WSDL, you still can specify contract yourselves and let frameworks do the transport work.

Ihar Voitka
in #1 so I have to install that just to get some header information in my API calls?
CoffeeAddict
#2, ok so how do I retrieve the data back from the response? I don't understand what you mean by WSE internals, that it does this for me under the covers? Ok but still how do I get the response data on x method call?
CoffeeAddict
I have found no good articles on any of this. Anything I have found is very top level. I knew nothing about WSE 3.0 and I don't understand why I would need to install something like this as an add on just to add SOAP headers. Wouldn't most people need that out of the box anyway if they are calling an outside web service?
CoffeeAddict
**ABSOLUTELY NOT** WSE 3.0 is obsolete! It should not be used unless there is no other choice.
John Saunders
I agree, it is better to invest more time into WCF learning and stay up-to-date.
Ihar Voitka
Man, it's not just a matter of staying up to date! WSE is dead and should be buried instead of stinking up new projects! It was an interiim product from the start, is based on ASMX, which is, itself, now "legacy" code not getting bugs fixed, and there's very, very, little reason to ever use it on anything new.
John Saunders
+1  A: 

I'm assuming you are using a web reference for this. For the most part, using the web service should be as easy as using a local object. .NET handles all of the plumbing under the covers. Sometimes this works very nicely -- other times not so much.

When you add a web reference to the PayPal web service Visual Studio will create a file in a sub-folder of Web References called reference.cs which is the proxy class (by default VS 2008 hides it -- you have to "show all files" to see it).

For your specific case, it looks like PayPal is using custom SOAP headers to transmit all of the security context information. Take a look at the CustomSecurityHeaderType and the UserIdPasswordType types for more details. Also, some documentation from PayPal might help. :)

To use the service you will have to do something like this:

    PayPalAPISoapBinding payPal = new PayPalAPISoapBinding();

    CustomSecurityHeaderType customSecurity = new CustomSecurityHeaderType();
    customSecurity.eBayAuthToken = "The Auth Token";

    UserIdPasswordType userId = new UserIdPasswordType();
    userId.Password = "PWD";
    userId.Username = "JIMMY";

    customSecurity.Credentials = userId;

    payPal.RequesterCredentials = customSecurity;

    RefundTransactionReq request = new RefundTransactionReq();

    RefundTransactionResponseType response = payPal.RefundTransaction(request);

I'm not familiar with the PayPal service but I think this is how it should work.

Tuzo
Yes, I'm going to be using a Web Reference in .NET 3.5
CoffeeAddict
Interesting, so you have to use their types. I can't just create an HTtpWebRequest and HttpWebResponse. Likewise you're using their objects to create what's passed over as the soap header information.
CoffeeAddict
This really helps jump start me a lot. I just couldn't find any examples and so I resorted to posting here. So darn, this means that I can't just use .nET objects entirely for the request/response properties.
CoffeeAddict
It's not like: I *have* to use their types. :( It's more like: Yes! I can use *their* types. :)
Tuzo
+4  A: 

There's serious confusion here. Everybody please STOP!

WSE is obsolete. Don't use it.

"Web References" relate to the old ASMX web service technology. Microsoft now considers it to be "legacy" code and has stopped fixing bugs. Don't use it if you don't have to.

The OP should use "Add Service Reference". I just tried it, and it worked.


Now, to your questions:

  1. How can I specify header params?

    Because this service uses headers, the proxy classes have been generated as Message Contracts, which can have header parts, and body parts. For instance, the RefundTransactionRequest class has a RequesterCredentials property which is of the CustomSecurityHeaderType type. You simply set that before sending the request. In fact, it has generated a constructor for RefundTransactionRequest that takes both the header and the body as parameters, so this is easy.

  2. How is the request/response objects handled?

    You don't have to do anything except create instances of classes, and call methods. All the serialization is done for you. All the class creation is done for you.

  3. When I receive the response, does the Proxy class contain its state?

    Yes. The proxy class will contain all message header and body parts. Of course, there will only be a header part if there was an output header.

  4. When ever would I want to instead just create custom code like I did before and not use web services/reference option with WSDL?

    Never, I think. I've never seen a reason to do so. I guess the only time would be if there was a bug in "Add Service Reference".


Example:

using (var svc = new PayPalAPIAAInterfaceClient())
{
    var paypal = (PayPalAPIInterface) svc;
    var credentials = new CustomSecurityHeaderType
                          {
                              Credentials =
                                  new UserIdPasswordType
                                      {
                                          AppId = "",
                                          Username = "John",
                                          Password = "John"
                                      }
                          };
    var request = new RefundTransactionRequestType
                      {
                          Amount =
                              new BasicAmountType
                                  {
                                      currencyID = CurrencyCodeType.USD,
                                      Value = "100.00"
                                  },
                          Memo = "I want my money back",
                          RefundType = RefundType.Full,
                          RefundTypeSpecified = true
                      };
    var refundRequest = new RefundTransactionReq
                            {RefundTransactionRequest = request};
    var result =
        paypal.RefundTransaction(
            new RefundTransactionRequest(credentials, refundRequest));
    var response = result.RefundTransactionResponse1;
    var returnedCredentials = result.RequesterCredentials;
}
John Saunders
Thank you. Its these answers I typically can't find just on MSDN...the inferred parts of this which you just stated.
CoffeeAddict
And I did not know I had to use their objects (PayPal) to create the request and get the response. I figured that would be done with a .NET object. Now I understand. For instance I didn't really get that I had to use CustomSecurityHeaderType and RequesterCredential because my mind was still thinking in manual mode vs. a web service over wsdl
CoffeeAddict
John just curious. I looked at their API. Where did you see the credentials param when looking at the API reference for RefundTransactionRequest. Actually where did you see any information at all about CustomSecurityHeaderType or UserIdPasswordType in their API documentation?
CoffeeAddict
And I'm wondering what if any classes I could create to abstract any of the redundancy out of this. Otherwise I don't see a need to create anything and just start using the proxy class in my code behind. I just think I could create some helper methods and a utility class to somehow abstract out the redundancy of having to create and set a CustomSecurityHeaderType each and every time I want to use this in my code-behind
CoffeeAddict
I just looked in the Reference.cs file. If you click on your project in Solution Explorer, and click the "Show all files" button in the Solution Explorer toolbar, you'll find "+" signs next to many files - and next to the service references. Click the "+" signs to expand the service reference. Eventually, you'll come to a Reference.cs file, which is a _very_ large file full of proxy classes. It was not pleasant to go through that, even using ReSharper, and I don't understand the use of explicit interface implementation, but it got the above code to compile.
John Saunders