How to: Query List Items from the Host Web in a Client Web Part of a SharePoint Hosted app
Posted
Friday, October 26, 2012 8:30 AM
by
CoreyRoth
That’s a mouthful, but I wanted to make sure that people knew exactly what this post is for. The problem I am seeing out there already is that while there is a lot of code samples, they aren’t clear for what type of app the sample is for. If you are doing a provider hosted app for example, the way you query list items is different (using the Cross-Domain Library). Today’s topic boggled me though because while I found plenty of samples on how to query list items using CSOM from an app, they were all in-fact incorrect for a SharePoint hosted app. The article I linked is great by the way. It has many of the things you need to know how to do via CSOM in an app so be sure and check it out.
Now to get on to the scenario I want to help you with today. If you are building a Client Web Part, you may have stumbled upon my previous articles on the topic (JavaScript and Getting Started). These are great articles to get you started, however, it turns out I left out the details on how to query list items from a SharePoint hosted app. Like many things, it’s not as simple as I thought it was. I thought it was just a matter of passing another URL into get_web(). I was wrong. I then saw some examples and thought I just need to pass the URL into a new SPContext object. Also wrong. While, you can do that, once you make the call to get your list items, you’ll quickly find yourself with an Access Denied error coming from MicrosoftAjax.js. I gave up and posted something to the forums and luckily Elisabeth Olson from MSFT came through with the answer. In my solution, I start with some global variable declarations.
var context;
var web;
var user;
var spHostUrl;
var parentContext
Then the code looks similar to that from my article on SP.js. In the document ready function, I get the spHostUrl with the following line of code. You can get that getQueryStringParameter method from my previous article as well. Remember, the SPHostUrl comes from the {StandardTokens} parameter in your Client Web Part’s elements.xml file.
spHostUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));
Now, we set up our context and here is where things are a bit different. First, we get our context object using SP.ClientContext.get_current() as usual. However, we have to get a new context by using SP.AppContextSite and passing in the current context along with the Host Url.
context = new SP.ClientContext.get_current();
parentContext = new SP.AppContextSite(context, spHostUrl);
After that, we just need to get our SPWeb object using the parentContext.
web = parentContext.get_web();
At this point, it’s business as usual to do our queries. Get the list, set a CAML query, load the getItems call, and then execute the query.
var list = web.get_lists().getByTitle("My List"));
var camlQuery = new SP.CamlQuery();
camlQuery.set_viewXml("");
this.listItems = list.getItems(camlQuery);
context.load(listItems);
context.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed));
My success and failure functions are pretty standard in this case. I just manually iterate through the results and return the Title and Id. Otherwise, I display the reason for failure.
function onQuerySucceeded() {
$("#results").empty();
var listInfo = '';
var listEnumerator = listItems.getEnumerator();
listInfo += "<table><tr><th>Id</th><th>Title</th></tr>";
while (listEnumerator.moveNext()) {
var listItem = listEnumerator.get_current();
listInfo += '<tr><td>' + listItem.get_item('ID') + '</td>'
+ '<td>' + listItem.get_item('Title') + '</td>'
+ '</tr>\n';
}
listInfo += '</table>';
$("#results").html(listInfo);
}
function onQueryFailed(sender, args) {
$("#results").empty();
$("#results").text('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
This threw me for a loop for a while, so hopefully this post helps you get started quicker when you build your app.
Follow me on twitter, @coreyroth, if you have any questions and come see me at SPC if you are going.