Saturday, 19 July 2008

Deleting Folders in MOSS via Web Services and CAML

Unfortunately, the lists.asmx web service that you use to manipulate MOSS lists doesn't have a "Delete()" method for folders. However, there is an "UpdateListItems()" method that allows you to pass in an Xml element parameter called "batchElement" to provide this functionality. You then can manipulate folders in Sharepoint to your hearts content through this parameter.

The typical format for the batch element Xml fragment is:

<Batch OnError='Return'>
<Method ID='1' Cmd='Delete'>
<Field Name='ID'>81</Field>
<Field Name='FileRef'>http://dev-moss/sites/home/PropertySharePoint/DocumentLibrary/300</Field>
</Method>
</Batch>


Your delete is successful if the return value is zero. You can test this out in the U2U CAML query builder from http://www.u2u.info/Blogs/Patrick/Lists/Posts/Post.aspx?ID=1315



This batchElement information can be passed into the sharepoint list web service as demonstrated in the method snippet below:



  /// <summary>

        /// Delete folders as per http://msdn2.microsoft.com/en-us/library/ms429658.aspx for LPP-205

        /// </summary>

        /// <param name="listName"></param>

        /// <param name="folderName"></param>

        /// <returns></returns>

        public XmlNode DeleteFolder(string listName, string folderName)

        {

            /*Use the CreateElement method of the document object to create elements for the parameters that use XML.*/

            System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();

            XmlElement query = xmlDoc.CreateElement("Query");

            XmlElement viewFields = xmlDoc.CreateElement("ViewFields");

            XmlElement queryOptions = xmlDoc.CreateElement("QueryOptions");

            string rowLimit = int.MaxValue.ToString();

            /*To specify values for the parameter elements (optional), assign CAML fragments to the InnerXml property of each element.*/

            System.Text.StringBuilder sb= new System.Text.StringBuilder();

            sb.Append("<Where><Eq><FieldRef Name=\"Title\" />");

            sb.Append(string.Format("<Value Type=\"Text\">{0}</Value></Eq></Where>", folderName));

            viewFields.InnerXml = "<FieldRef Name=\"ID\" /><FieldRef Name=\"Title\" />";

            query.InnerXml =  sb.ToString();

            queryOptions.InnerXml = "";

            System.Xml.XmlNode nodeListItems = _listWebService.GetListItems(listName, string.Empty, query, viewFields, rowLimit, queryOptions, null);

            string folderId = string.Empty;

            string fileRef = string.Empty; 

            XmlDocument doc = new XmlDocument();

            doc.LoadXml(nodeListItems.InnerXml);

            XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);

            nsmgr.AddNamespace("z", "#RowsetSchema");

            nsmgr.AddNamespace("rs", "urn:schemas-microsoft-com:rowset");

            XmlNodeList xmlNodeList = doc.SelectNodes("/rs:data/z:row", nsmgr);

            foreach (XmlNode node in xmlNodeList)

            {

                folderId = node.Attributes["ows_ID"].Value;

                //fileRef = node.Attributes["ows_EncodedAbsUrl"].Value;

                fileRef = node.Attributes["ows_FileRef"].Value.Substring(node.Attributes["ows_FileRef"].Value.IndexOf("#") + 1);

                break;

            }

            System.Xml.XmlNode result = null; //Will be populated response from update batch.

            if (folderId != string.Empty)

            {

                System.IO.StringWriter sw = new System.IO.StringWriter();

                System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(sw);

                xw.WriteStartDocument();

                // build batch node

                xw.WriteStartElement("Batch");

                xw.WriteAttributeString("OnError", "Return");

                // Build method node

                xw.WriteStartElement("Method");

                // Set transaction ID - doesn't really matter what the number is

                xw.WriteAttributeString("ID", System.Guid.NewGuid().ToString("n"));

                xw.WriteAttributeString("Cmd", "Delete");

                // Build field ID

                xw.WriteStartElement("Field");

                xw.WriteAttributeString("Name", "ID");

                xw.WriteString(folderId);

                xw.WriteEndElement(); // Field end

                // Build FileRef

                xw.WriteStartElement("Field");

                xw.WriteAttributeString("Name", "FileRef");

                xw.WriteString(fileRef);

                xw.WriteEndElement(); // Field end

                xw.WriteEndElement(); // Method end

                xw.WriteEndElement(); // Batch end

                xw.WriteEndDocument();

                System.Xml.XmlDocument batchElement = new System.Xml.XmlDocument();

                batchElement.LoadXml(sw.GetStringBuilder().ToString());

                //Setup web service

                // send update request to sharepoint to create the document folder

                result = _listWebService.UpdateListItems(listName, batchElement);

            }

            return result;

        }

1 comment:

vikings said...

Thanks Buddy...It works like a charm....It save my one day