UpdateListItems Web Service fails when using item level permissions

This tip come from one of my colleagues, but it’s a good ‘un:
For those of you familiar with the Lists.asmx web service in SharePoint, you’ll know that the UpdateListItems() method allows you to apply metadata to a list item. The following XML provides a simple example of how I’ve been using it so far….
<Method ID='1' Cmd='Update'>
<Field Name='ID' />
<Field Name='FileRef'>http://site/library/folder1/folder2/mydoc.pdf</Field>
<Field Name='ContentType'>Invoice</Field>
<Field Name='InvoiceNumber'>12345</Field>
</Method>
Under normal circumstances, the above XML works just fine. However, if you enable fine grained permissions [Item Level Permissions] in a document library it will break with a permissions related error (even though you have permissions to perform the action!)In this situation what you MUST do is also pass in a value for the ID field, otherwise it won’t work. E.g.:
<Method ID='1' Cmd='Update'>
<Field Name='ID' >57</Field>
<Field Name='FileRef'>http://site/library/folder1/folder2/mydoc.pdf</Field>
<Field Name='ContentType'>Invoice</Field>
<Field Name='InvoiceNumber'>12345</Field>
</Method>
If you’re performing a HTTP PUT to upload your document, you won’t know the ID value, so you’ll need make another web service call to retrieve it. E.g.
XmlNode query = xmlDoc.CreateNode(XmlNodeType.Element, "Query", string.Empty);
query.InnerXml = "&lt;Where&gt;&lt;Eq&gt;&lt;FieldRef Name='FileRef'/&gt;&lt;Value Type='Note'&gt;" + EscapeXmlValue(uri.Path.Substring(1)) + "&lt;/Value&gt;&lt;/Eq&gt;&lt;/Where&gt;";
XmlNode viewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", string.Empty);
viewFields.InnerXml = "&lt;FieldRef Name='ID'/&gt;";
XmlNode queryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", string.Empty);
queryOptions.InnerXml = "&lt;QueryOptions&gt;&lt;ViewAttributes Scope='Recursive' /&gt;&lt;/QueryOptions&gt;";
XmlNode node = _listsWebService.GetListItems(listGuid, null, query, viewFields, "1", queryOptions, null);
XmlNodeList items = node.SelectNodes("rs:data/z:row", _nsm);
if (items.Count == 0) {
return null;
} else {
//document found.  Return the ID
return items[0].Attributes["ows_ID"].Value;
}
}
I would recommend that peeps check through their code to see where they use the UpdateListItem() method and make sure they’re populating the ID value; otherwise things could go pop when the customer switches on fine grained permissions.
Advertisements
UpdateListItems Web Service fails when using item level permissions

13 thoughts on “UpdateListItems Web Service fails when using item level permissions

  1. Dan Mayernik says:

    By “enable fine grained permissions [Item Level Permissions]” -do you mean that you changed a specific item’s security in the library or do you mean the library itself is no longer inheriting from the site?

    I have a situation very similar to yours -except that the ContentType field “refuses” to change. All calls result in the content type being set to the library’s default content type regardless of what I pass in. My library is not inheriting form the site.

    Any thoughts?

    thanks,

    Dan

    Like

  2. Hi Dan,

    I mean that the Items no longer inherits permissions from the Library – so yes, we changed a specific item’s security without affecting security for other items in the library. Once you’ve done that, by the way, that library ALWAYS has fine grained permissions, even if you change the permissions back.

    Anyway, to your question – what message do you get back from the web service? Would it be something like the document is uploaded as a default content type and checked in? Then you update on the content type & metadata might be refused ‘cos checkout was required.

    Are you updating an item that you just uploaded or something?

    Like

  3. Well, yes. I don’t know what else you might be wanting to do in the Batch. You’ve got to figure out some of what you want to do yourself! But the code I’ve posted was the core of what I was having to do, and it worked for me 🙂

    Like

  4. Hi Andy,

    I believe this is applicable to SharePoint 2010 as well. I’m trying to associate the ID of a file I previously uploaded to my SP2010 server and was wondering about the XmlNamespaceManager _nsm object you reference. Where and how should I declare it?

    thanks!

    -Paul

    Like

  5. Tom says:

    This post was GREAT and saved me a TON of time after racking my brain over why I was getting a “The URL provided contains an invalid Command or Value. Please check the URL again.” error in the responseXml. I thought having the ID in the Method would’ve been enough, didn’t think it was needed as a field, too. Again, GREAT POST and THANK YOU!!!!

    -Tom

    Like

  6. Tom says:

    For anyone trying to use that Method group alone, you can’t – you need to do it like this:

    [edit] Ok, fields messed up when copying, above, because of the “less than” and “greater than” tags in the code, so let’s do it like this: wherever you see “%”, that means use the “less than” or “greater than” sign.

    var xmlFields = "";
    xmlFields += "<Method ID='1' Cmd='Update'>";
    xmlFields += "<Field Name='ID'>1</Field>";
    xmlFields += "<Field Name='MyColumn'>" + valueToUpdate + "</Field%>";
    xmlFields += "</Method%";

    var xmlEnvelope = "";
    xmlEnvelope += "<?xml version='1.0' encoding='utf-8' ?>";
    xmlEnvelope += "<soap:Envelope xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'%";
    xmlEnvelope += "<soap:Body>";
    xmlEnvelope += "<UpdateListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>";
    xmlEnvelope += "<listName>My List</listName>";
    xmlEnvelope += "<updates>";
    xmlEnvelope += "<Batch OnError='Return'>";
    xmlEnvelope += xmlFields;
    xmlEnvelope += "</Batch>";
    xmlEnvelope += "</updates>";
    xmlEnvelope += "</UpdateListItems>";
    xmlEnvelope += "</soap:Body>";
    xmlEnvelope += "</soap:Envelope>";

    var xmlResult = new ActiveXObject("MSXML2.XMLHTTP");
    var xmlDoc = new DOMParser();
    var xmlCommand = new DOMParser();
    var bOK = false;

    xmlCommand = xmlEnvelope;
    HTTP.open("POST",webServiceUrl,false);
    HTTP.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/sharepoint/soap/" + webServiceName);
    HTTP.setRequestHeader("Content-Type", "text/xml; charset=utf-8);
    HTTP.send(xmlCommand);
    bOK = xmlDoc.parseFromString(HTTP.responseText, "text/xml");
    HTTP = null;
    xmlCommand = null;

    if (!bOK) {
    alert("Error loading XML from HTTP");
    }
    else
    return bOK;

    Like

  7. Chris McClain says:

    Andy —

    I have code to update the meta-data on a document in a document library. The code is working perfectly for SharePoint 2007 Versions 12.0.0.6219 and 12.0.0.6421. However moving to a new SharePoint instance, 12.0.6545, the call to UpdateListItems() returns 0x81020030. (“Invalid file name”). This fails only for document libraries.

    xml = “” +
    “” +
    “4” +
    “http://xxx/sites/training/Test/test.doc” +
    “2007-12-02T00:00:00Z” +
    “”;

    doc.LoadXml(xml);

    XmlNode batchNode = doc.SelectSingleNode(“//Batch”);

    listProxy.Url = “http://xxxx/sites/training/_vti_bin/lists.asmx”;
    listProxy.UseDefaultCredentials = true;

    XmlNode resultNode = listProxy.UpdateListItems(listID, batchNode);

    The result is:

    0x81020030Invalid file name

    The file name you specified could not be used. It may be the name of an existing file or directory, or you may not have permission to access the file.

    <z:row

    ows_Modified="2011-03-30 14:18:31"

    ows_Modified_x0020_By="2011-03-24 14:34:22"……etc……

    Notice the ows_Modified_x0020_By is changed, but ows_Modified is not.

    Have you ever seen this error? Thanks if you have any ideas, I've been working on this for days (and days) now……

    Like

  8. Chris McClain says:

    Oops – sorry, I forgot the code tags – hopefully this looks better:

    xml = "<Batch OnError='Continue' PreCalc='TRUE'>" +
    "<Method ID='1' Cmd='Update'>" +
    "<Field Name='ID'>1</Field>" +
    "<Field Name='FileRef'>http://xxx/sites/training/Test/test.doc</Field>" +
    "<Field Name='Modified'>2011-03-24 14:34:22</Field>" +
    "</Method></Batch>";

    Like

  9. Nope, sorry, that’s a new one on me. However, Modified By should be a user, not a datetime – so I wonder how that happened. That’s a pretty big error!

    Like

  10. Manoranjan says:

    Hi Chris,
    We are also facing the same error. The same code using UpdateListItems is working fine in SharePoint 2007 but not in Sharepoint 2010. Throws the error code “0x81020030The URL is invalid”. Can you please share us the steps if you manage to resolve this error.

    Regards,
    Mano

    Like

  11. Nigel Tunnicliffe says:

    Hi Andy

    This post was an absolute life-saver after our live Sharepoint 2007 environment suddenly decided to behave as if item level security was enabled even though are SharePoint team say the we do not use this feature. An application which had been working without any problems for 2 years suddenly started generating ‘Unexpected Error’ conditions when updating meta data virtually overnight.

    Are you aware of any other SharePoint options which would cause the ‘old’ method of updating meta data to stop working.

    Many thanks

    Nigel

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s