Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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.
  }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with sharepoint.stackexchange
scroll top