1

I’m trying to update some metadata with web services. I read following msdn article UpdateListItems and wrote a small test program, but sadly something went wrong. I get the error message, that the list is not found where I would like to change something. I would like to modify the metadata in a document library not only in a list.

If I execute XmlNode test = listService.GetList("{3c5c1ebd-1f19-4223-b162-e3d200c903f5}"); I get the attributes from the list. Everything looks fine, connection and so one works...

I create a new Batch to update the library with following attributes:

Batch.SetAttribute("OnError","Continue");
Batch.SetAttribute("PreCalc", "true");
Batch.SetAttribute("ListVersion","0");
Batch.SetAttribute("RootFolder", rootFolder);

rootFolder is test.Attributes["RootFolder"].Value + "/LibraryName";

The string batch looks like:

"<Method ID='1' Cmd='Update'>" +
"<Field Name='ID'>6VJWEENCP2DC-250-33</Field>" +
"<Field Name='Status'>1</Field></Method>";

What went wrong? Why would the list not be updated?

I get following error:

<Results xmlns="http://schemas.microsoft.com/sharepoint/soap/">
    <Result ID="1,Update">
        <ErrorCode>0x81020026</ErrorCode>
        <ErrorText>...List does not exist...</ErrorText>
    </Result>
</Results>

Edit Here a little bit more code.

webportal.Lists listService = new webportal.Lists();
listService.Credentials = System.Net.CredentialCache.DefaultCredentials;

XmlNode test = listService.GetList("{3c5c1ebd-1f19-4223-b162-e3d200c903f5}");
string rootFolder = test.Attributes["RootFolder"].Value + "/Library Name";

string strBatch =
    "<Method ID='1' Cmd='Update'>" +
    "<Field Name='ID'>6VJWEENCP2DC-250-34</Field>" +
    "<Field Name='Name_x002C__x0020_Firstname'>Yeahaa!</Field></Method>";            

XmlDocument xmlDoc = new System.Xml.XmlDocument();
System.Xml.XmlElement elBatch = xmlDoc.CreateElement("Batch");
elBatch.SetAttribute("OnError","Continue");
elBatch.SetAttribute("PreCalc", "true");
elBatch.SetAttribute("ListVersion","1");
elBatch.SetAttribute("RootFolder", rootFolder);
//elBatch.SetAttribute("ViewName", "{8e208951-1455-46de-9566-032de23fb2d9}");

elBatch.InnerXml = strBatch;

XmlNode ndReturn = listService.UpdateListItems("{3c5c1ebd-1f19-4223-b162-e3d200c903f5}", elBatch);

Edit2 Now I have changed my code and I’m using the client object model. The access to the libraries works very well. Now I would like to access to the folder in the library and change the metadata there. But if I change the siteurl to the folder path, I get an exception that the _vti_bin/sites.asmx is not found.

Here is my code (working code for libraries):

string siteurl = "http://webportal/dokumente/site";
ClientContext clientContext = new ClientContext(siteurl);

Web site = clientContext.Web;
clientContext.Load(site, s => s.Title);
clientContext.ExecuteQuery();

List list = clientContext.Web.Lists.GetByTitle("library");
CamlQuery query = new CamlQuery();
query.ViewXml =
@"<View>
    <Query>
        <Where>
            <Eq>
                <FieldRef Name='Title' />
                <Value Type='Text'>test</Value>
            </Eq>
        </Where>
    </Query>
</View>";
ListItemCollection list2 = list.GetItems(query);
clientContext.Load(list2);
clientContext.ExecuteQuery();

How could I fix this? How could I access to the folder and change the metadata?

  • How does the call to UpdateListItems look? Do you use the Guid as ListName? Have you tried to include a Field element with FileRef? – Per Jakobsen Mar 13 '12 at 10:08
  • Look at my Edit I have copied the code part in it. I use the GUID . I haven’t tried it with FileRef, how does it works with FileRef? – user5167 Mar 13 '12 at 10:34
  • If you look at the example "Update documents" in the MSDN article you linked to the specify FileRef pointing to the document. I can't remember if it's needed. I mainly work with SP2010, so I don't use the WebService anymore – Per Jakobsen Mar 13 '12 at 10:46
  • Is there a better way in SP2010? – user5167 Mar 13 '12 at 10:47
  • YES, in SP2010 you can use either the Client Side Object Model or the REST interface, both are a lot better than the old WebServices – Per Jakobsen Mar 13 '12 at 10:53
1

For the following examples I've created:

  • a site called MySubSite in my sitecollection http://sharepoint.
  • a document library called "My Doc Lib"
  • added a column "FirstName"
  • a folder called "My Folder"
  • uploaded a document called mydoc.txt to both the root and "My folder"

The following code finds the mydoc.txt inside "My folder" and changes FirstName.

Using the listdata.asmx web service the code is:

private static void UseWebService()
{
    var listService = new webportal.Lists();
    listService.Url = "http://sharepoint/MySubSite/_vti_bin/Lists.asmx";
    listService.Credentials = System.Net.CredentialCache.DefaultCredentials;
    var lists = listService.GetListCollection();
    var nsm = new XmlNamespaceManager(lists.OwnerDocument.NameTable);
    nsm.AddNamespace("ns", "http://schemas.microsoft.com/sharepoint/soap/");
    var listNode = lists.SelectSingleNode("//ns:List[@Title='My Doc Lib']", nsm);
    var listName = listNode.Attributes["Name"].Value;

    var listInfo = listService.GetList(listName);
    string rootFolder = listInfo.Attributes["RootFolder"].Value;

    XmlDocument xmlDoc = new System.Xml.XmlDocument();
    XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element,"Query","");
    XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element,"QueryOptions","");
    ndQueryOptions.InnerXml = string.Format("<Folder>{0}/My Folder</Folder>", rootFolder);
    ndQuery.InnerXml = "<Where><Eq><FieldRef Name='FileLeafRef'/>" + 
        "<Value Type='Text'>MyDoc.txt</Value></Eq></Where>";

    var items = listService.GetListItems(listName, null, ndQuery, null, "1", ndQueryOptions, null);
    var nsm2 = new XmlNamespaceManager(items.OwnerDocument.NameTable);
    nsm2.AddNamespace("ns", "#RowsetSchema");
    var item = items.SelectSingleNode("//ns:row", nsm2);
    var itemId = item.Attributes["ows_ID"].Value;

    string strBatch = "<Method ID='1' Cmd='Update'>" +
        string.Format("<Field Name='ID'>{0}</Field>", itemId) +
        "<Field Name='FirstName'>Updated using WS</Field></Method>";

    System.Xml.XmlElement elBatch = xmlDoc.CreateElement("Batch");
    elBatch.SetAttribute("OnError", "Continue");
    elBatch.SetAttribute("PreCalc", "true");
    elBatch.SetAttribute("ListVersion", "1");

    elBatch.InnerXml = strBatch;

    XmlNode ndReturn = listService.UpdateListItems(listName, elBatch); 
}

Using the client object mode the code is:

private static void UseClientObjectModel()
{
    string siteurl = "http://sharepoint/MySubSite";
    var clientContext = new ClientContext(siteurl);

    Web site = clientContext.Web;

    List list = clientContext.Web.Lists.GetByTitle("My Doc Lib");
    Folder rootFolder = list.RootFolder;
    clientContext.Load(rootFolder);
    clientContext.ExecuteQuery();

    CamlQuery query = new CamlQuery();
    query.ViewXml = @"<View> 
  <Query> 
    <Where> 
      <Eq> 
        <FieldRef Name='FileLeafRef' /> 
        <Value Type='Text'>mydoc.txt</Value> 
      </Eq> 
    </Where> 
  </Query> 
</View>";
    query.FolderServerRelativeUrl = string.Format("{0}/My Folder", rootFolder.ServerRelativeUrl);
    ListItemCollection items = list.GetItems(query);
    clientContext.Load(items);
    clientContext.ExecuteQuery();
    var item = items[0];
    item["FirstName"] = "Updated from Client Object Model";
    item.Update();
    clientContext.ExecuteQuery();
}

And using the REST api (listdata.svc) the code is:

private static void UseRest()
{
    var context = new MySubSiteDataContext(new Uri("http://sharepoint/mysubsite/_vti_bin/listdata.svc"));
    context.Credentials = System.Net.CredentialCache.DefaultCredentials;
    var items = from d in context.MyDocLib
                where d.Name == "mydoc.txt"
                && d.Path == "/MySubSite/My Doc Lib/My folder"
                select d;
    var item = items.First();
    item.FirstName = "Updated using REST";
    context.UpdateObject(item);
    context.SaveChanges();
}

My preference is to use Client side object model to find things like the server relative path to the root folder and the use REST for dealing with the data

  • I added the query.FolderServerRelativeUrl = string.Format("{0}/My Folder", rootFolder.ServerRelativeUrl); into my code and everything works like charm with the com way. Thank you!!! – user5167 Mar 14 '12 at 8:55
1

try changing your query to this:

"<View Scope='RecursiveAll'>
    <Query>
        <Where>
            <Eq>
                <FieldRef Name='Title' />
                <Value Type='Text'>test</Value>
            </Eq>
        </Where>
    </Query>
</View>"

http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.client.viewscope.aspx

You can also try: (This is code is not tested)

List list = clientContext.Web.Lists.GetByTitle("library");
CamlQuery query = new CamlQuery.CreateAllFoldersQuery()
ListItemCollection listItems = list.GetItems(query);
clientContext.Load(listItems);
clientContext.ExecuteQuery();

foreach(ListItem item in listItems)
{
  if(item.FileSystemObjectType == FileSystemObjectType.Folder)
  {
      //Do Something.
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy