Using CAML to update multiple list items

May 17, 2011 at 12:10 PM

I am aware of two kinds of updates that can be done using SPServices. One is a single item update using the value pairs and the other is a multiple item update when you need to update one or more fields across multiple items with the same values. But I am in a situation where I need to update different fields/values for different items. Is it possible to do something like this through the CAML query? I am trying this code but it is giving me a POST error:

 

update_string = "<Batch OnError='Continue'>" +
    "<Method ID='145' Cmd='Update'>" +
        "<Field Name='FullName'>John Doe</Field>" +
        "<Field Name='Email'>John.Doe@doe.com</Field>" +
    "</Method>" + 
    "<Method ID='148' Cmd='Update'>" +
        "<Field Name='FullName'>Foo Bar</Field>" +
        "<Field Name='Email'>Foo.Bar@doe.com</Field>" +
    "</Method>" + 
    "</Batch>";

$().SPServices({
    operation: "UpdateListItems",
    async: false,
    listName: "ContactList",
    updates: update_string,
    completefunc: function(xData, Status) {
        console.log(xData.responseText);
    }
});

Coordinator
May 17, 2011 at 12:29 PM

nileshc:

You're not specifying the item ID in the Method properly. In the line:

"<Method ID='145' Cmd='Update'>"

the ID is simply a number you use so that you can check the results in the response. You need to specify the item ID in the Fields you specify (assuming that the IDs you were specifying for the Method ID are actually the item IDs):

update_string = "<Batch OnError='Continue'>" +
    "<Method ID='1' Cmd='Update'>" +
        "<Field Name="ID">145<Field>" +
        "<Field Name='FullName'>John Doe</Field>" +
        "<Field Name='Email'>John.Doe@doe.com</Field>" +
    "</Method>" + 
    "<Method ID='2' Cmd='Update'>" +
        "<Field Name="ID">148<Field>" +
        "<Field Name='FullName'>Foo Bar</Field>" +
        "<Field Name='Email'>Foo.Bar@doe.com</Field>" +
    "</Method>" + 
    "</Batch>";

Check the UpdateListItems documentation in the MSDN SDK for details. Remember that the Web Services aren't mine, but microsoft's. SPServices simply "wraps" them for easier use.

M.

May 17, 2011 at 1:15 PM

ah, sorry, my mistake. Should have seen the documentation properly. Thanks, sympmarc. :)

Coordinator
May 17, 2011 at 1:16 PM

No problem!

M.

May 17, 2011 at 2:53 PM
Edited May 17, 2011 at 8:07 PM

I tried with the correct positioning of the item ID. But I still get a 400 Bad request from the server. Here is the XML that is being submitted to the server (captured from Google Chrome console):

 

<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/'>
    <soap:Body>
        <UpdateListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>
            <listName>ContactList</listName>
            <updates>
                <Batch OnError='Continue'>
                    <Method ID='1' Cmd='Update'>
                        <Field Name="ID">145<Field>
                        <Field Name='FullName'>John Doe</Field>
                        <Field Name='Email'>John.Doe@doe.com</Field>
                    </Method>
                    <Method ID='2' Cmd='Update'>
                        <Field Name="ID">148<Field>
                        <Field Name='FullName'>Foo Bar</Field>
                        <Field Name='Email'>Foo.Bar@doe.com</Field>
                    </Method>
                </Batch>
            </updates>
        </UpdateListItems>
    </soap:Body>
</soap:Envelope>

Any idea, where I could be going wrong? The documentation mentions about 'ListVersion' & 'ViewName' attributes for the <Batch> tag. Are they required? I know the XML content is actually a question for the MSDN forums. But looking at the JS code I have used, am I missing some important parameter to be set?

Coordinator
May 17, 2011 at 2:58 PM

Are you trying to update a list or a library? If it's a Document Library, then you need to specify the FileRef as well as the ID. (I know, it doesn't really make sense -- I didn't write it!)

Also, is the list or library that you are updating in the same site? If not, you need to specify the webURL.

M.

May 17, 2011 at 2:59 PM

It is a list. And yes, it is the same site, so I guess the webURL is not required.

Coordinator
May 17, 2011 at 3:02 PM
Edited May 17, 2011 at 3:10 PM

Hmm. Well, the first thing I'd try is a simple GetListItems on that list to make sure that I could get to it via Web Services. Then I'd try a single update.

I also always do my dev work in IE, as there are fewer variables in play.

M.

May 17, 2011 at 3:07 PM
Edited May 17, 2011 at 3:08 PM

Right, I am doing something similar too. Here, I am actually fetching the list items from the List and displaying them in a form (For various reasons,  I am not using Infopath or other means to update the items). The user can edit the items and then submit back to the server. So the data fetching works just fine and a single item update works too. I even tried looping the single item updates. But obviously that is not a good practice! So I am trying to update all items in a single update!

Coordinator
May 17, 2011 at 3:14 PM

OK, so it's the multiple update methods that is causing the issue. Good to know that you're further along than I knew about.

Aha! I think it's my bad: <Field Name="ID">145</Field> I didn't have the </Field> right in what I pasted to you.

M.

May 17, 2011 at 7:55 PM

No, it's not your mistake. It's mine. While pasting I copied from the example you had given. In the original console log, the '</Field>' is rightly there. I was sanitizing my data when pasting here :) I'll do one thing. I'll give this problem a little rest and come back to it in a few hours. Hopefully I will see where I am making a mistake.

May 17, 2011 at 8:16 PM

Just for your reference, here is the original JS code again (field names have been sanitized):

function save_contacts(form_dom_id) {
    var serialized_data = $(form_dom_id).serializeObject();
    var update_string = "<Batch OnError='Continue'>";
    for (i=0; i<(serialized_data.contact_id.length); i++) {
        update_string += "<Method ID='"+(i+1)+"' Cmd='Update'>";
        update_string += "<Field Name='ID'>"+serialized_data.contact_id[i]+"</Field>";
        update_string += "<Field Name='FullName'>"+serialized_data.full_name[i]+"</Field>";
        update_string += "<Field Name='Email'>"+serialized_data.email[i]+"</Field>";
        update_string += "</Method>";
    }
    update_string += "</Batch>";
    
    $().SPServices({
        operation: "UpdateListItems",
        async: false,
        batchCmd: "Update",
        listName: "ContactList",
        updates: update_string,
        completefunc: function(xData, Status) {
		    console.log(xData.responseText);
		    alert("Changes submitted");
        }
    });
}

Coordinator
May 18, 2011 at 3:36 PM

Any success?

M.

May 19, 2011 at 10:06 AM

I made some progress. :) Now the combined update works if the array consists of 3 or less items. If the items are more than 3, again the same 400 BAD Request! Very strange! :) Something fishy here. Investigating further.

May 20, 2011 at 4:25 AM

Marc, finally found the issue. It was an offending row (4th in the list) which was causing all the pain. I had changed the properties of a few columns and this row had old data. Two days wasted for a single row!

Learnt that it is better to clear out the list items completely before testing. I am able to update 20+ items in one go now. :)

Coordinator
May 20, 2011 at 6:18 AM
Whew! Glad you worked it out. I wasn't sure what to suggest next.

M.
>
May 20, 2011 at 6:21 AM

Yes, I guessed as much. After spending so much time reading the documentation carefully and googling, I finally looked back at my own data.

 

Thanks for all your help.