views:

575

answers:

2

I had a webmethod working which returned a byte array to the caller:

public byte[] DownloadPDF(string URI)

I had to change this to return another output (a string). So, I decided to change the method completely by now returning void and having 3 parameters like this:

public void DownloadFile(string URI, out byte[] docContents, out string returnFiletype)

My web service compiles correctly but I suspect something is wrong with the 2nd parameter (i.e. the byte array) because when I "Add Web Reference" and build my proxy class, the method has only 2 parameters, not 3):

[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DownloadFile", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    [return: System.Xml.Serialization.XmlElementAttribute("docContents", DataType="base64Binary")]
    public byte[] DownloadFile(string URI, out string returnFiletype) {
        object[] results = this.Invoke("DownloadFile", new object[] {
                    URI});
        returnFiletype = ((string)(results[1]));
        return ((byte[])(results[0]));
    }

I don't see why my 2nd parameter, the byte array, is being ignored, but it appears to be the source of the problem.

This of course messes me up in the web client app where I get an error message at compile time:

No overload for method 'DownloadFile' takes '3' arguments

Here is the code in the web client where I need to pass 3 arguments:

myBrokerASMXProxy.ASMXProxy.FileService client = new myASMXProxy.ASMXProxy.FileService();

        byte[] fileDataBytes;
        string fileType;
        client.DownloadFile(URI, fileDataBytes, fileType);

I am thinking of changing it back to return a byte array and add just a single "out" parameter but I thought I should ask you experts about this and in general, what is the best practice for handling multiple output requirements.

+1  A: 

The byte array isn't being ignored - it's being put as the return type instead. I don't know why it's doing that, but it makes more sense in my view. I wouldn't use out parameters in a void method. I suspect the proxy generator just takes any method with out parameters and turns the first one into a return type.

Jon Skeet
So, you agree one quick workaround would be to discard the void return and return a byte array instead leaving just 2 parameters: one input string and one out string)??
John Galt
Yes, that's what I'd do. Or create a new return type containing a string and a byte array, which might be somewhat nicer (and work better from languages without "out" parameters, such as Java).
Jon Skeet
+1  A: 

Why don't your try putting this signature:

public bool DownloadFile(string URI, out byte[] docContents, out string returnFiletype)

To see what happens? I agree with Jon Skeet, but you can still can return a bool with the result of the operation

Jhonny D. Cano -Leftware-
OK..still not sure why but your suggested signature (returning a bool) resulted in the proper signature in the proxy class generated (i.e. 1 input parm, a byte array output, and a string output). Is this mostly style or is there a best practice for multiple outputs? I could have returned a bytearray
John Galt
I think, as Jon said, the proxy generator optimized it for shorter SOAP messages, so put the first out parameter as a return type instaead of the void method
Jhonny D. Cano -Leftware-
This seems like a workaround rather than a solution - adding a dummy return type isn't particularly clean. (It was a good experiment to conduct, don't get me wrong - I just wouldn't want to use it in real life.)
Jon Skeet
Ok, the solution you provided is different and also works, Jon, i liked that too,... I just tried to do the simpler method signature that won't lead the proxy generator to generate a different method, that would be buggy on a long term.
Jhonny D. Cano -Leftware-