SPServices is a great tool, really nice work, Marc Anderson (@sympmarc). It has been there all the time I have developed for SharePoint. But the fact that you work with XML and you must parse the attributes (!) was the reason why I prefered listdata.svc and Client Object Model, where you get objects in JSON or you have a nice API to get objects and their properties. But there is an area where SPServices are really the best tool: SharePoint Web Services which only understand SOAP like SocialDataService.asmx.
Three ways to get list items
Just a little comparison. We’ll retrieve Titles from Tasks list (Oppgaver in nb-no).
listdata.svc
$.getJSON("/_vti_bin/ListData.svc/Oppgaver()?$select=Tittel") .done(function(data){ var tasks = data.d.results; for(var t in tasks) { var title = tasks[t].Tittel; console.log(title); } }) .fail(function() { console.log("error"); });
Pay attention to the field name: Tittel. I think it is the biggest shortcoming of listdata.svc: the fact that we can’t use the internal (static) field names.
Client Object Model
var ctx = SP.ClientContext.get_current(); var web = ctx.get_web(); var taskList = web.get_lists().getByTitle("Oppgaver"); var query = new SP.CamlQuery("<ViewFields><FieldRef Name='Title' /></ViewFields>"); var tasks = taskList.getItems(query); ctx.load(tasks); ctx.executeQueryAsync(function() { var listEnumerator = tasks.getEnumerator(); while(listEnumerator.moveNext()) { var task = listEnumerator.get_current(); var title = task.get_item("Title"); console.log(title); } }, function() { console.log("error"); });
SPServices
$().SPServices({ operation: "GetListItems", async: true, listName: "Oppgaver", CAMLViewFields: "<ViewFields><FieldRef Name='Title' /></ViewFields>", completefunc: function (xData, Status) { $(xData.responseXML).SPFilterNode("z:row").each(function() { console.log( $(this).attr("ows_Title") ); }); } });
SPServices and SocialDataService
Let’s try to find the count of comments for an url. To do so we must create a SOAP envelope in javascript, send it and handle the response result:
var strUrl = "http://dev/Sider/Help.aspx"; var request = "<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> \ <CountCommentsOnUrl \ xmlns='http://microsoft.com/webservices/SharePointPortalServer/SocialDataService'> \ <url>" + strUrl + "</url> \ </CountCommentsOnUrl> \ </soap:Body> \ </soap:Envelope>"; jQuery.ajax({ type: "POST", async: true, url: '/_vti_bin/SocialDataService.asmx?op=CountCommentsOnUrl', data: request, contentType: "text/xml; charset=utf-8", dataType: "xml", success: function (content, txtFunc, xhr) { var count = jQuery(content).find('CountCommentsOnUrlResult').text(); console.log(count); } });
It works but, we have to handle the creating of SOAP envelope in our javascript code which can be error prone. SPServices provides a nice abstraction layer and handles many scenarios. The same operation in SPServices:
$().SPServices({ operation: "CountCommentsOnUrl", async: true, url:"http://dev/Sider/Help.aspx", completefunc: function (xData, Status) { var result = $(xData.responseXML).find("CountCommentsOnUrlResult")[0]; console.log($(result).text()); } });
In both cases we have to iterate through responseXML. This is a sample responseXML for CountCommentsOnUrl from SocialDataService.asmx:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<CountCommentsOnUrlResponse
xmlns="http://microsoft.com/webservices/SharePointPortalServer/SocialDataService">
<CountCommentsOnUrlResult>1</CountCommentsOnUrlResult>
</CountCommentsOnUrlResponse>
</soap:Body>
</soap:Envelope>
