in

Dot Net Mafia

Group site for developer blogs dealing with (usually) .NET, SharePoint, Office 365, Mobile Development, and other Microsoft products, as well as some discussion of general programming related concepts.

This Blog

Syndication

Archives

Corey Roth [MVP]

A SharePoint MVP bringing you the latest time saving tips for SharePoint 2013, Office 365 / SharePoint Online and Visual Studio 2013.

How to: Query SharePoint 2013 using REST and JavaScript

I have a session coming up at SharePoint Summit Toronto this year about the many different ways you can query search.  Whenever I am working on a new talk, it is customary for me to write blog posts about my examples so here it is. :)  I first learned how to query SharePoint 2013 search with the new REST API and JavaScript from looking at examples from @ScotHillier on MSDN.  However, the last time I tried the example, I noticed an issue which I equate to most likely a change between beta and RTM.  This post shows you my version of how to query search using the REST API and JavaScript. 

For this post, I am using the RTM Office Developer tools (which I have a post coming out on soon).  I am going to use a SharePoint-hosted app for my example but you could also use this in a web part with farm solution as well.  When it comes to apps, you need to be sure and request permission to access search.  Do this by editing your AppManifest.xml and clicking on the permissions tab.  Select Search and then select QueryAsUserIgnoreAppPrincipal.  If you forget this step, you won’t get an error, your queries will simply just return zero results.

SearchAppRESTPermission

For my example, I am just going to add my code to the default.aspx page in the app.  I simply add a textbox, a button, and a div to hold the results.  The user will type in his or her query, click the button, and then see search results.  You could put this in a Client Web Part if you wanted. 

<div>

    <label for="searchTextBox">Search: </label>

    <input id="searchTextBox" type="text" />

    <input id="searchButton" type="button" value="Search" />

</div>

 

<div id="resultsDiv">

</div>

Now, we need to add the necessary code to App.js.  I start by removing the example code that retrieves the user information.  I instead, add a click handler to my searchButton to execute the search query.  If you remember from my previous post on REST, we assemble a URL by appending /api/search/query to a SharePoint host URL.  For example.

http://server/_api/search/query

However, in an app, we have to request the URL to the App.  One way to do this is by query string using the SPAppWebUrl parameter.  SharePoint passes this parameter to your app start page automatically.  We can request it with a line line this.  Remember getQueryStringParameter() is a helper method that we have gotten from some of the SharePoint examples.  I’ll include it in the full code listing at the bottom of this post.

var

spAppWebUrl = decodeURIComponent(getQueryStringParameter('SPAppWebUrl'));

To pass the user’s query to SharePoint, we need to include the querytext parameter on the REST URL.  Be sure to enclose the value in single quotes.  Again more details in my previous post.

http://server/_api/search/query?querytext=’SharePoint’

Now, we need to create a click handler for the search button, build the URL, and then execute the query.

$(

"#searchButton").click(function () {

});

Inside the click handler, assemble the URL, using the concatenation of the spAppWebUrl, /api/search/query, and the querytext parameter.  The value of querytext will be retrieved from the textbox we added earlier.

var queryUrl = spAppWebUrl + "/_api/search/query?querytext='" + $("#searchTextBox").val() + "'";

Now, we just execute the query with $.ajax().  Pass the queryUrl in the url parameter.   This example uses the GET method but if you have a lot of parameters, you may consider using POST instead.  Lastly, this part is key to get this example to work.  The accept header must have value of "application/json; odata=verbose".  The odata=verbose part is not in the MSDN example.  If you leave it out, you will receive an error.  The last parameters are the methods that will handle the success and failure of the AJAX call.  Here’s what the whole method looks like.

$("#searchButton").click(function () {

    var queryUrl = spAppWebUrl + "/_api/search/query?querytext='" + $("#searchTextBox").val() + "'";

 

    $.ajax({ url: queryUrl, method: "GET", headers: { "Accept": "application/json; odata=verbose" }, success: onQuerySuccess, error: onQueryError });

});

Now, you need to write code to handle the success.  The results come back in JSON format, but unfortunately, they are buried in a hugely nested structure.  Each individual result can be found in data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results.  Your best bet is to assign this a variable and then use a template or manually parse it. In my example, I am just going to use $.each to iterate through the results using brute force.  The individual columns of each search result can be found in this.Cells.results.Value.  Ok, that’s confusing I am sure, so let’s look at the code and then step through it.  I’m just writing out a simple table by appending HTML tags to a div.

function onQuerySuccess(data) {

    var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;

 

    $("#resultsDiv").append('<table>');

 

    $.each(results, function () {

        $("#resultsDiv").append('<tr>');

        $.each(this.Cells.results, function () {

            $("#resultsDiv").append('<td>' + this.Value + '</td>');

        });

        $("#resultsDiv").append('</tr>');

    });

 

    $("#resultsDiv").append('</table>');

}

Effectively, I have two nested loops.  One to iterate through each result and one for each managed property (column) in the results.  When you get inside the Cell, this.Value will show the value of the result while this.Key will contain the name of the managed property. 

The last thing to implement is the code to handle errors.  It’s relatively simple and just writes error.StatusText to the div.

function onQueryError(error) {

    $("#resultsDiv").append(error.statusText)

}

When I run my app, here is what it looks like.

SearchAppDefault

Executing a query in the app, gives us results but they aren’t pretty.  You can pretty them up yourself. :)  It also doesn’t include anything to print out the managed property names on the table.  You could get the names by looking at each cell of the first result and using this.Value.

SearchAppResults

You can see, it’s really pretty easy to get started.  You can further refine your REST query to request specific fields, sort orders, and more.  I’ll probably write a follow-up post in the future to include some of those details. Here’s the whole source code for my example that you can work with.

var context = SP.ClientContext.get_current();

 

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model

$(document).ready(function () {

 

    var spAppWebUrl = decodeURIComponent(getQueryStringParameter('SPAppWebUrl'));

 

    $("#searchButton").click(function () {

        var queryUrl = spAppWebUrl + "/_api/search/query?querytext='" + $("#searchTextBox").val() + "'";

 

        $.ajax({ url: queryUrl, method: "GET", headers: { "Accept": "application/json; odata=verbose" }, success: onQuerySuccess, error: onQueryError });

    });

 

});

 

function onQuerySuccess(data) {

    var results = data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results;

 

    $("#resultsDiv").append('<table>');

 

    $.each(results, function () {

        $("#resultsDiv").append('<tr>');

        $.each(this.Cells.results, function () {

            $("#resultsDiv").append('<td>' + this.Value + '</td>');

        });

        $("#resultsDiv").append('</tr>');

    });

 

    $("#resultsDiv").append('</table>');

}

 

function onQueryError(error) {

    $("#resultsDiv").append(error.statusText)

}

 

//function to get a parameter value by a specific key

function getQueryStringParameter(urlParameterKey) {

    var params = document.URL.split('?')[1].split('&');

    var strParams = '';

    for (var i = 0; i < params.length; i = i + 1) {

        var singleParam = params[i].split('=');

        if (singleParam[0] == urlParameterKey)

            return decodeURIComponent(singleParam[1]);

    }

}

That’s all there is to it.  Hopefully, you find this example useful.  Thanks.

The complete Visual Studio for this code snipped has also been uploaded to MSDN Code Samples.

Comments

 

How to: Query SharePoint 2013 using REST and Ja... said:

Pingback from  How to: Query SharePoint 2013 using REST and Ja...

April 19, 2013 12:29 PM
 

Dharyl said:

Hi Corey,

When you said (on your slides) that using REST + Javascript is "great for" Apps and Web Parts, what do you mean with Apps?

Do you mean remote/custom web apps? Our search application is currently built using custom ASP.Net web application and is not using the OOB SharePoint 2010 pages and is deployed in a separate farm outside the SharePoint farm.

What is the best approach for us to run queries against the REST API considering establishing trusts for authentication?

May 29, 2013 4:10 AM
 

CoreyRoth said:

@Dharyl good question.  Honestly, it is good for both.  Even when you are remotely hosted, a lot of people are using client side calls.  However, for remote apps, people tend to go with the Managed Client OM and you have to make use of TokenHelper.cs for authentication.

July 16, 2013 11:02 AM
 

Lina Jibreel said:

please im trying to get the itemcount for SharePoint list in "specific view"  any help please??

July 16, 2014 5:13 AM
 

Neha Bhushan said:

Hi Lina, came across your query today(i guess a little late). To fetch itemCount for the items in specified View, you need to define View via CAML query:

var context= SP.clientContext.get_current();

var list = context.get_web().get_Lists.GetByTitle("Enter Your List Name");

//Once you have the list, prepare your CAML query

var query="</VIEW>"

var camlQuery.set_viewXML= query;

var items = list.getItems(camlQuery);

var count= items.count();//Please check the syntax to this

alert('The item count is: '+ count)

April 8, 2015 9:10 AM
 

Jim Shelley said:

As is, your code works great on my 365 SharePoint site. However, in testing the other REST APIs, I changed the query to return items from just a list like so:

var queryUrl = spAppWebUrl + "/_api/web/lists/getbytitle('Movies')/Items";

This gives me a NOT FOUND status text message even though I changed the permissions in the AppManifest file (List = Full Control, Web = Full Control)

Is there something else I need to do to retrieve all the List Items?

August 21, 2015 9:23 AM

Leave a Comment

(required)  
(optional)
(required)  
Add

About CoreyRoth

Corey Roth is an independent SharePoint consultant specializing in ECM, Apps, and Search.
2015 dotnetmafia.
Powered by Community Server (Non-Commercial Edition), by Telligent Systems