WEBSITE

Sharepoint 2010 : Client Object Model - Retrieving Data

9/29/2013 9:35:42 PM
As you saw in the preceding code snippets, although the Client Object Model defines client-side representations of server objects and we can create instances of those objects in our code, the objects are not populated with a copy of the server-side data until it is explicitly loaded.

In-place Load

This Silverlight code snippet shows how to execute a Collaborative Application Markup Language (CAML) query against a list:

private void CAMLQUery_Click(object sender, RoutedEventArgs e)
{
ClientContext ctx = new ClientContext("Your site here");
CamlQuery query = new CamlQuery();
query.ViewXml = "<View><Query><OrderBy>
<FieldRef Name=\"Editor\" Ascending=\"False\" />
</OrderBy></Query></View>";
List announcements = ctx.Web.Lists.GetByTitle("Announcements");
FieldCollection fields = announcements.Fields;
ctx.Load(fields);
ListItemCollection listItems = announcements.GetItems(query);
ctx.Load(listItems);
ctx.ExecuteQueryAsync((s, args) =>
{
Dispatcher.BeginInvoke(() =>
{
BuildTable(fields, listItems);
});
}, (s, args) =>
{
Dispatcher.BeginInvoke(() =>
{
label1.Content = args.Message;
});
});
}



To perform the same function using JavaScript, you can use this:

function CAMLQuery_Click() {
var ctx = new SP.ClientContext.get_current();
var query = new SP.CamlQuery();
query.viewXml = "<View><Query><OrderBy>
<FieldRef Name=\"Editor\" Ascending=\"False\" />
</OrderBy></Query></View>";
var announcements = ctx.get_web().get_lists().getByTitle("Announcements");
var listItems = announcements.getItems(query);
ctx.load(listItems);
var fields = announcements.get_fields();
ctx.load(fields);
ctx.executeQueryAsync(function (s, args) {
var console = document.getElementById('DemoConsole');
console.innerHTML = buildTable(fields,listItems);
}, null);
}



The important thing to note about these code samples is the use of the ClientContext.Load method. This method flags the passed in object to be populated the next time ExecuteQueryAsync is called, so in the preceding example, ctx.Load(listItems) will flag the listItems object for population.

To use these code snippets with the demo project that we set up earlier, take the following steps—first, for the Silverlight sample:

  1. Add a new button labeled Execute CAML Query to MainPage.xaml, and set the Click event handler to CAMLQuery_Click.

  2. Add the Silverlight code snippet listed above into MainPage.xaml.cs.

  3. Add a ScrollViewer control to MainPage.xaml and then, inside the ScrollViewer, add a Grid control named grid1.

  4. Add the following code into MainPage.xaml.cs:

    void BuildTable(FieldCollection fields, ListItemCollection listItems)
    {
    grid1.RowDefinitions.Clear();
    grid1.ColumnDefinitions.Clear();
    grid1.ShowGridLines = false;
    grid1.RowDefinitions.Add(new RowDefinition {
    Height=new GridLength(0,GridUnitType.Auto)});
    int i = 0;
    foreach (var field in fields)
    {
    if (!field.Hidden)
    {
    grid1.ColumnDefinitions.Add(new ColumnDefinition {
    Width=new GridLength(0,GridUnitType.Auto)
    });
    TextBlock label = new TextBlock
    {
    Text = field.Title,
    HorizontalAlignment = HorizontalAlignment.Center,
    FontWeight = FontWeights.Bold,
    Margin = new Thickness(10, 0, 10, 0),
    };
    label.SetValue(Grid.RowProperty, 0);
    label.SetValue(Grid.ColumnProperty, i);
    grid1.Children.Add(label);
    i++;
    }
    }
    int row = 1;
    foreach (var item in listItems)
    {
    i = 0;
    grid1.RowDefinitions.Add(new RowDefinition {
    Height=new GridLength(0,GridUnitType.Auto)});
    foreach (var field in fields)
    {
    if (!field.Hidden)
    {
    TextBlock label = new TextBlock {
    HorizontalAlignment = HorizontalAlignment.Center,
    Margin = new Thickness(10, 0, 10, 0),
    };
    try
    {
    label.Text = item[field.StaticName].ToString();
    }
    catch (Exception)
    {
    label.Text = "--";
    }
    label.SetValue(Grid.RowProperty, row);
    label.SetValue(Grid.ColumnProperty,i);
    i++;
    grid1.Children.Add(label);
    }
    }
    row++;
    }
    }


  5. Build the SilverlightCOMDemo project.

    Now, for the JavaScript sample, do the following:

    1. Using SharePoint Designer, modify JavascriptTest.aspx to include an additional button.

    2. Above the DemoConsole div tag that we added earlier, insert the following markup:

      <input name="Button2" type="button" value="Execute CAML Query"
      onclick="CAMLQuery_Click()"></input>
  6. Within the JScriptTest.js file in our SharePoint project, add the CAMLQuery_Click JavaScript sample method listed above and then add the following function:

    function buildTable(fields,listItems) {
    var output = "";
    output = "<table><thead style=\"font-weight:bold\"><tr>";
    var fieldEnum = fields.getEnumerator();
    while (fieldEnum.moveNext()) {
    var field = fieldEnum.get_current();
    if (field.get_hidden() != true) {
    output += "<td>" + field.get_title() + "</td>";
    }
    }
    output += "</tr></thead>";
    var enumerator = listItems.getEnumerator();
    while (enumerator.moveNext()) {
    var item = enumerator.get_current();
    fieldEnum.reset();
    output += "<tr>";
    while (fieldEnum.moveNext()) {
    var field = fieldEnum.get_current();
    if (field.get_hidden() != true) {
    try {
    output += "<td>" + item.get_item(field.get_staticName()) + "</td>";
    } catch (e) {
    output += "<td>--</td>";
    }
    }
    }
    output += "</tr>";
    }
    output += "</table>"
    return output;
    }
Object Identity

Although property values are not populated until they are explicitly loaded, it is still possible to make use of the properties in expressions, as long as the expressions themselves are not enumerated until after the properties are loaded. In our code sample, we can see an example of this in the following line:

List announcements = ctx.Web.Lists.GetByTitle("Announcements");

If we were to attempt to enumerate any of the properties of the announcements object, an error would be thrown since the value has not been initialized. The same is also true of the properties of the object referred to by the ctx.Web property. We can use the property in an expression because an expression uses a reference to the property rather than its actual value.

You can see that our code sample makes use of the announcements object in various places, but we never explicitly populate it. Loading an object is necessary only if its properties will be converted to a value.

One easy way to look at it is to consider that each object is a proxy for an appropriate server-side object. Using the proxy, we can perform many of the same actions, but until we explicitly load data from the real object into the proxy, we can’t use the data on the client side because it exists only on the server.

Filtering Returned Data

When we execute the preceding code samples, a table is generated containing the field values that are returned for each list item, as shown:

This works well and doesn’t present much of a problem when only a few items are included in the list or library. But what happens if tens of thousands of items are included and we need only one or two columns? Transferring all this redundant data to the client would have a major performance impact.

Thankfully, we can eliminate redundant data by filtering the properties that are populated by the Load method, as the following snippets show. To see the results of these samples, create a new button and hook up the Click event to the sample code, as we’ve done in the past few samples.

Here’s the snippet in Silverlight:

private void FilterQuery_Click(object sender, RoutedEventArgs e)
{
ClientContext ctx = new ClientContext("Your site here");
CamlQuery query = new CamlQuery();
query.ViewXml = "<View><Query><OrderBy>
<FieldRef Name=\"Editor\" Ascending=\"False\" />
</OrderBy></Query></View>";
List announcements = ctx.Web.Lists.GetByTitle("Announcements");

FieldCollection fields = announcements.Fields;
ctx.Load(fields,
fs => fs.Include(
f => f.Hidden,
f => f.Title,
f => f.StaticName).Where(f => f.Hidden == false)
);
ListItemCollection listItems = announcements.GetItems(query);
ctx.Load(listItems,
items => items.Include(
item => item["Title"]
));
ctx.ExecuteQueryAsync((s, args) =>
{
Dispatcher.BeginInvoke(() =>
{
BuildTable(fields, listItems);
});
}, (s, args) =>
{
Dispatcher.BeginInvoke(() =>
{
label1.Content = args.Message;
});
});
}



And here’s the JavaScript:

function FilteredQuery_Click() {
var ctx = new SP.ClientContext.get_current();
var query = new SP.CamlQuery();
query.viewXml = "<View><Query><OrderBy>
<FieldRef Name=\"Editor\" Ascending=\"False\" />
</OrderBy></Query></View>";
var announcements = ctx.get_web().get_lists().getByTitle("Announcements");
var listItems = announcements.getItems(query);
ctx.load(listItems,"Include(Title)");
var fields = announcements.get_fields();
ctx.load(fields,"Include(Hidden,Title,StaticName)");
ctx.executeQueryAsync(function (s, args) {
var console = document.getElementById('DemoConsole');
console.innerHTML = buildTable(fields, listItems);
}, null);
}

In the Silverlight sample, we’re making use of lambda expressions and Language Integrated Query (LINQ) to filter the returned data. Because LINQ syntax isn’t supported by JavaScript, we’re using a string containing a filter expression. When creating JavaScript filter strings, LINQ operations such as Where are not supported.

You can see that by running these samples, the resulting table contains only the Title column. Although you can’t see it from the output, the population of the fields collection has been filtered to include only the properties that are required for the logic. The result of these changes is that the data exchanged between client and server is greatly reduced.

Note

When querying lists or libraries, you need to be aware of how filtering is applied behind the scenes. First, the CAML query object passed into the GetItems method is used to retrieve a list of items into memory. With the item list in memory, LINQ to Objects is used to apply the filters that we’re defining with the Load method. This is significant, because when you’re querying large lists, item-level filtering should always be done using CAML to reduce the memory usage on the server.


Queryable Load

In addition to the ClientContext.Load method used in the preceding examples, the Client Object Model also provides a ClientContext.LoadQuery method. The difference between these two methods is in the object that receives the results of the method. When calling Load, we’ll pass in a reference to the object that we want to load along with any filtering expression; when the method has executed, that object that we passed in is loaded with the appropriate data. With LoadQuery, when the method has executed, an IEnumerable(T) collection is returned.

You may be wondering about the benefits of such a subtle difference between these methods. The main benefit is that LoadQuery can accept a LINQ query as a parameter; also, the results returned can be further processed using LINQ.

In the preceding Silverlight example, we could replace this

FieldCollection fields = announcements.Fields;
ctx.Load(fields,
fs => fs.Include(
f => f.Hidden,
f => f.Title,
f => f.StaticName).Where(f => f.Hidden == false)
);

with this:

var filteredFields = announcements.Fields.Include(
f => f.Hidden,
f => f.Title,
f => f.StaticName);

var fields = ctx.LoadQuery(from f in filteredFields
where f.Hidden == false
select f);

In the second example, the fields variable contains an IEnumerable<Field> object as opposed to the FieldCollection object that would be populated with the first example.

Although the JavaScript object model also includes the loadQuery method, since JavaScript doesn’t support LINQ, its primary function is to return the results as a separate variable rather than populating the appropriate ClientContext property. Other than that, there is no real benefit to using loadQuery in JavaScript.

Other  
  •  Sharepoint 2010 : Client Object Model - Available Client-side Objects
  •  Sharepoint 2010 : Client Object Model - Architecture , Demonstration Environment Setup
  •  Developer Tools for SharePoint 2013 : Troubleshooting with Debugging
  •  Developer Tools for SharePoint 2013 : Setting Up Your Development Environment
  •  Developer Tools for SharePoint 2013 : Understanding Visual Studio 2012 Tools (part 3) - SharePoint Solutions
  •  Developer Tools for SharePoint 2013 : Understanding Visual Studio 2012 Tools (part 2) - Applications for SharePoint
  •  Developer Tools for SharePoint 2013 : Understanding Visual Studio 2012 Tools (part 1) - SharePoint Connections in Server Explorer
  •  Developer Tools for SharePoint 2013 : Understanding SharePoint Designer 2013
  •  Developer Tools for SharePoint 2013 : Customization Options with SharePoint , OOB Developer Experience
  •  Sharepoint 2013 : Understanding Your Development Options (part 5) - Creating ASPX Pages, Creating Master Pages
  •  
    Top 10
    Review : Sigma 24mm f/1.4 DG HSM Art
    Review : Canon EF11-24mm f/4L USM
    Review : Creative Sound Blaster Roar 2
    Review : Philips Fidelio M2L
    Review : Alienware 17 - Dell's Alienware laptops
    Review Smartwatch : Wellograph
    Review : Xiaomi Redmi 2
    Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
    Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
    3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
    REVIEW
    - First look: Apple Watch

    - 3 Tips for Maintaining Your Cell Phone Battery (part 1)

    - 3 Tips for Maintaining Your Cell Phone Battery (part 2)
    VIDEO TUTORIAL
    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

    - How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
    Popular Tags
    Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone
    Visit movie_stars's profile on Pinterest.