In a previous post, I wrote about watching out for data type mismatches when using the CFSharePoint tag.  While this is all well and good, much of my post was based on  a misconception of how an "inout parameter" works.  While I can't claim great knowledge of this, I think I have a better understanding.

From what I understand, an inout parameter expects a specifically named parameter–let's say "Result"–to be passed in.  When you pass this parameter to the web service, the value, or "out", should be the variable that you want returned.  So if I want the "results" parameter to return its value as "finalResults", you could do something like:

results="finalResults"

In the last post, I was under the impression that the initial value of "results" HAD to be a ColdFusion data type, like a structure or array.  This is not correct.  Sure, I can pass in the appropriate data type with the "results" parameter; however, whatever structure I pass in will overwrite the "out".  This is why if you run the example I provided in the last post, copying an "About.doc" file from one folder to another will really just create a new "About.doc" with the value of the binary object I passed to it–"a."  This is because by passing in the binary object on the "in", I inadvertantly overwrote what would normally be returned in the "out".

So if you really want to use SharePoint web services to copy files from one folder to another, you'll have to combine two methods: GetItem and CopyIntoItems.  Fortunately, now that I know how inout parameters work, this is cake.

Let's look at the GetItem call real quick:

<cfsharepoint    action="getItem"
        domain="localhost/mysite"
        userName="xxxx"
        password="xxx"
        name="sourceDoc"
        wsdl="http://localhost/mysite/_vti_bin/Copy.asmx?wsdl"
        params="#{                                       

 

            URL="http://localhost/mysite/Shared%20Documents/About.doc",
            fields="sourcefields",
            stream="sourcestream",
            getItemResult="getItemResult"
        }#"
/>

Nothing much to this.  However, you should note a few things.  For "fields", notice how I'm not passing a ColdFusion variable.  Rather, I'm simply naming the "out" of the fields parameter.  The same is true for "stream."  Instead of declaring that this should be equal to some ColdFusion binary object, I'm simply naming what I want the "out" of this parameter to be.

Now, if run this and dump the results for fields and stream, I'll get a collection of methods for the FieldCollection, and the binary "stream" of the source URL I provided.  Sweet!

 

Of course, I think now you're onto what comes next.  Let's plop in the example from before:

<cfscript>
    function SmartArray(lItems,delim){
    var ArrayContainer=StructNew();
    ArrayContainer.string=ListToArray(lItems,delim);
    return ArrayContainer;
    }
</cfscript>
<cfscript>
    destinationUrls = smartArray("http://localhost/mysite/Shared%20Documents/Sub-Directory/About.doc",",");
</cfscript>

<cfsharepoint    action="CopyIntoItems"
        domain="localhost/mysite"
        userName="xxxx"
        password="xxxx"
        name="destDoc"
        wsdl="http://localhost/mysite/_vti_bin/Copy.asmx?wsdl"
        params="#{
            sourceUrl="http://localhost/mysite/Shared%20Documents/About.doc",
            destinationUrls="#destinationURLs#",
            fields="#sourcefields#",
            stream="#sourcestream#",
            copyIntoItemsResult="copyIntoResult",
            results="finalResults"
        }#"
/>

If you recall the last example, I was passing empty (or mostly empty) ColdFusion variables for the fields and stream parameters.  This was a mistake.  While the fields and stream parameters on the GetItem method are inout parameters, they are NOT such for CopyIntoItems.  Rather, these are run-of-the-mill parameters that don't return an "out," so obviously they need real data.  

Fortunately, because of our success with the GetItem method, we have the right information.  Using the "outs" provided from the fields and stream parameters in our first web service invocation, we can pass these real, correctly data-typed values to the fields and stream parameters of the CopyIntoItems method.

That's it!  Now we have successfully created a mechanism for copying files in SharePoint!