Home > PowerShell, SharePoint > SPWeb.ProcessBatchData throws “Value does not fall within the expected range” exception

SPWeb.ProcessBatchData throws “Value does not fall within the expected range” exception

September 29th, 2009 nas Leave a comment Go to comments

Recently I needed to delete a large number of items from List and I tried to solve it by simply invoking Delete() method on each SPListItem object.

Function Clear-List([Microsoft.SharePoint.SPList]$list) {
  $list.Items | ForEach-Object { $_.Delete() }
}

That did the trick but I wasn’t really satisfied with the results – the code was deleting an item every 2-3 seconds. That made me looking for alternative approache and eventually I came across http://merill.net/2008/02/efficiently-delete-purge-all-items-from-a-sharepoint-list/, it was looking like a solution to my problem, so I took the idea and built my own function using XmlTextWriter instead of StringBuilder.

When I tried to run it, I was surprised – it didn’t work. The ProcessBatchData method was throwing Value does not fall within the expected range exception for no apparent reason, so I switched back to StringBuilder method from original article and that surprised me again – it worked.

That intrigued me enough to start annihilating any difference between generated XML strings by both methods. I was shocked when during my very last iteration, I discovered the case of encoding declaration to be cause for this exception. Take a look by yourself:

A non working document declaration produced by XmlTextWriter.WriteStartDocument() method:

<?xml version="1.0" encoding="utf-8"?>

A working document declaration produced by code from article:

<?xml version="1.0" encoding="UTF-8"?>

Looks like a bug with ProcessBatchData method – maybe someday I will open up a case with Microsoft but for now as a workaround we can simply either fallback to StringBuilder method or replace utf-8 with UTF-8 before invoking ProcessBatchData method.

Function Clear-List([Microsoft.SharePoint.SPList]$list) {
  $requestStream = New-Object System.IO.MemoryStream
  $requestWriter = New-Object System.Xml.XmlTextWriter($requestStream, [System.Text.Encoding]::UTF8)

  $requestWriter.WriteStartDocument()
  $requestWriter.WriteStartElement("Batch")

  $list.Items | ForEach-Object {
    $requestWriter.WriteStartElement("Method")
    $requestWriter.WriteStartElement("SetList")
    $requestWriter.WriteAttributeString("Scope", "Request")
    $requestWriter.WriteString($list.ID)
    $requestWriter.WriteEndElement()
    $requestWriter.WriteStartElement("SetVar")
    $requestWriter.WriteAttributeString("Name", "ID")
    $requestWriter.WriteString($_.ID)
    $requestWriter.WriteEndElement()

    if($list.BaseType -eq [Microsoft.SharePoint.SPBaseType]::DocumentLibrary) {
      $requestWriter.WriteStartElement("SetVar")
      $requestWriter.WriteAttributeString("Name", "owsfileref")
      $requestWriter.WriteString($_.File.ServerRelativeUrl)
      $requestWriter.WriteEndElement()
    }

    $requestWriter.WriteStartElement("SetVar")
    $requestWriter.WriteAttributeString("Cmd", "Delete")
    $requestWriter.WriteEndElement()
    $requestWriter.WriteEndElement()
  }

  $requestWriter.WriteEndElement()
  $requestWriter.WriteEndDocument()

  $requestWriter.Flush()

  $requestStream.Seek(0, [System.IO.SeekOrigin]::Begin)

  $requestReader = New-Object System.IO.StreamReader($requestStream)
  $requestText = $requestReader.ReadToEnd()
  $requestStream.Close()
  $requestText = $requestText.Replace("utf-8", "UTF-8")

  $result = $list.ParentWeb.ProcessBatchData($requestText)
}
Categories: PowerShell, SharePoint Tags:
  1. No comments yet.
  1. No trackbacks yet.