1

Closed

SharePoint Utility - Buggy RemoveFiles method

description

Hello,
 
I think there is a bug in the RemoveFiles method of SharePoint Utility assembly (ListsServiceUtility.vb) :
 
At line 328-329 of ListsServiceUtility.vb file, the list name is not passed as parameter, but a hard coded value :
 
        Dim data = listsProxy.GetSharePointListItemData( _
            "Documents", viewName, New String() {"FileRef", "ID"}, , False, 300)
 
 
It should be
        Dim data = listsProxy.GetSharePointListItemData( _
            listName, viewName, New String() {"FileRef", "ID"}, , False, 300)
Closed Jan 23 at 6:27 AM by kevinidzi

comments

cpassuel wrote Jun 25, 2012 at 11:24 AM

As a workaround, i created a document library maned "Documents" with 3 files i have an error when running the script (i pass these 3 files in parameters) :

Error: 0x1 at SCR Supprimer fichier SP: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: There must be elements to process.
at Microsoft.Samples.SqlServer.SSIS.SharePointUtility.Adapter.ListsAdapter.ExecuteSharePointUpdateBatch(String listName, String viewId, XElement batchXml, Int16 batchSize)
at Microsoft.Samples.SqlServer.SSIS.SharePointUtility.ListServiceUtility.RemoveFiles(Uri sharepointUri, NetworkCredential credentials, String listName, String viewName, IEnumerable1 localFilePathList)
at Microsoft.Samples.SqlServer.SSIS.SharePointUtility.ListServiceUtility.RemoveFiles(Uri sharepointUri, String listName, String viewName, IEnumerable
1 localFilePathList)
at ST_36f2c6421d3047bf8db3e1608f28c527.vbproj.ScriptMain.Main()


In the SharePoint log, i see only the SOAP request for GetListItems :
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<GetListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <listName>Documents</listName>
  <query>
    <Query xmlns="" />
  </query>
  <viewFields>
    <ViewFields xmlns="">
      <FieldRef Name="FileRef" />
      <FieldRef Name="ID" />
    </ViewFields>
  </viewFields>
  <rowLimit>300</rowLimit>
  <queryOptions>
    <QueryOptions xmlns="">
      <IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns>
      <IncludeAttachmentUrls>FALSE</IncludeAttachmentUrls>
      <Paging ListItemCollectionPositionNext="" />
      <ViewAttributes Scope=""></ViewAttributes>
    </QueryOptions>
  </queryOptions>
</GetListItems>
</s:Body>
</s:Envelope>

cpassuel wrote Jun 26, 2012 at 4:31 PM

I think there is another bug at line 328-329 : the view name is passed as parameter, i think it should be viewId instead

Dim data = listsProxy.GetSharePointListItemData( _
listName, viewId, New String() {"FileRef", "ID"}, <Query/>, False, 300)

cpassuel wrote Jun 26, 2012 at 5:09 PM

I found another bug : The fileref field is in the format [version]#[subsites hierachy]/[listname]/[filename], not [version]#[listname]/[filename]

The query doesn't support this case so when your document library is in a sub site the join query won't return anything explaining the There must be elements to process exception

cpassuel wrote Jun 27, 2012 at 1:27 PM

As a quick workaround, i modified the query in RemoveFiles method (line 333-339 of ListServiceUtility.vb) to join on the filename only (after the last "/") instead of full path and it works well.
        Dim batchItems = From fn In localFilePathList _
                         Join sf In data On sf("FileRef").Substring(sf("FileRef").LastIndexOf("/") + 1) Equals fn _
                         Select _
                            <Method Cmd="Delete">
                                <Field Name="ID"><%= sf("ID") %></Field>
                                <Field Name="FileRef"><%= targetUri.AbsoluteUri + fn %></Field>
                            </Method>

cpassuel wrote Jul 3, 2012 at 2:19 PM

Here is the fixed version of RemoveFiles method
''' <summary>
''' Remove files from a SharePoint Document Library
''' </summary>
''' <param name="sharepointUri">URL to the SharePoint site or subsite that has the list</param>
''' <param name="listName">Document Library List Name</param>
''' <param name="localFilePathList">List of local full paths of files to remove</param>
''' <returns></returns>
''' <remarks>
''' Fixed version of RemoveFiles
''' </remarks>
Public Shared Function RemoveFiles( _
        ByVal sharepointUri As Uri, ByVal credentials As NetworkCredential, ByVal listName As String, ByVal viewName As String, _
        ByVal localFilePathList As IEnumerable(Of String)) _
    As XElement

    Using listsProxy = New ListsAdapter(sharepointUri, credentials)

        ' Get the target URI to upload the files to
        Dim targetUri = GetSharePointTargetUri(sharepointUri, listName)

        Dim viewId As String = listsProxy.LookupViewName(listName, viewName)

        ' Get the list items to match against the file ref in order to get the ID needed for deleting the files
        ' FIX : pass listName and viewId instead of "Documents" and viewName
        Dim data = listsProxy.GetSharePointListItemData( _
            listName, viewId, New String() {"FileRef", "ID"}, <Query/>, False, 300)

        ' Join the files in the list with the fileref field from SharePoint.
        ' The fileref field is in the format [version]#[listname]/[filename], so we need to do a bit of work to get something that joins
        ' FIX : The query should join filename with the filename in library (starting from the last "/")
        Dim batchItems = From fn In localFilePathList _
                         Join sf In data On sf("FileRef").Substring(sf("FileRef").LastIndexOf("/") + 1) Equals fn _
                         Select _
                            <Method Cmd="Delete">
                                <Field Name="ID"><%= sf("ID") %></Field>
                                <Field Name="FileRef"><%= targetUri.AbsoluteUri + fn %></Field>
                            </Method>
        Dim batchXml = <batch><%= batchItems %></batch>

        ' FIX : Do an UpdateBatch ONLY if there are items to process
        If batchItems.Elements.Count > 0 Then
            Return listsProxy.ExecuteSharePointUpdateBatch(listName, viewId, batchXml, 250)
        End If
    End Using

End Function

wrote Jan 23 at 6:26 AM

WOW.. thank you so much for the debugging and making this quite a bit more robust.

wrote Jan 23 at 6:27 AM

Resolved with changeset 97874.

kevinidzi wrote Jan 23 at 4:12 PM

A new version has been released, please try it out (marked beta)