Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

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?

share|improve this question
    
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? –  hofmeister 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? –  hofmeister 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

2 Answers 2

up vote 1 down vote accepted

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

share|improve this answer
    
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!!! –  hofmeister Mar 14 '12 at 8:55

try changing your query to this:

"<View Scope='RecusrsiveAll'>
    <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.
  }
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.