Loading Specific Values Using Lambda Expressions and the SharePoint CSOM API with Windows PowerShell

Gary Lapointe

by Gary Lapointe on 3/31/2015

Share this:
Print

Article Details

Date Revised:
6/17/2015

Applies to:
lambda expressions, PowerShell, SharePoint CSOM API


In the article, Using the SharePoint CSOM API with SharePoint Online and Windows PowerShell, I explained that when you call the ClientContext object’s Load method that only a subset of properties are typically loaded, usually most of the simple types, and that you’ll need to make another call to the Load method to get additional properties. But what if you want to explicitly load those additional properties or explicitly restrict the properties that are loaded to an even smaller set of properties? If you’re using C# you can do this very easily using something known as lambda expressions. Lambda expressions let us do all kinds of different things, but for our purposes here it essentially allows you to specify the properties to load. Consider the following C# example, which explicitly loads just the AllProperties collection object and the Title and Url properties of the Web object:

var web = ctx.Web;
ctx.Load(web, w => w.AllProperties, w => w.Title, w => w.Url);
ctx.ExecuteQuery();

This next example loads the Web’s Fields collection populating just the InternalName and Id properties of each Field object within the collection:

var web = ctx.Web;
ctx.Load(web, w => w.Fields.Include(f => f.Id, f=> f.InternalName));
ctx.ExecuteQuery();

If you’re new to lambda expressions, the syntax might look a little odd and a breakdown of its syntax is out of scope for this article, but in general this looks pretty straightforward, right? So now you should be asking if you can do that in PowerShell. The answer is, sort of. Unfortunately you can’t do lambda expressions in PowerShell but it is possible to achieve the same thing – with a Godzilla-sized amount of code! Well, maybe not that much code, but a whole lot by comparison. Lambda expressions are ultimately just a C# language construct that, behind the scenes, is compiled down to .NET code (other languages like VB.NET have lambda expression support as well but the syntax is different). The following snippet is an example of what the code for the first of the two previous examples would look like if written in .NET 2.0 without the convenience of the lambda expression syntax:

ParameterExpression expression;
Web clientObject = ctx.Web;
ctx.Load<Web>(clientObject, new Expression<Func<Web, object>>[] { Expression.Lambda<Func<Web, object>>(Expression.Property(expression = Expression.Parameter(typeof(Web), "w"), (MethodInfo) methodof(Web.get_AllProperties)), new ParameterExpression[] { expression }), Expression.Lambda<Func<Web, object>>(Expression.Property(expression = Expression.Parameter(typeof(Web), "w"), (MethodInfo) methodof(Web.get_Title)), new ParameterExpression[] { expression }), Expression.Lambda<Func<Web, object>>(Expression.Property(expression = Expression.Parameter(typeof(Web), "w"), (MethodInfo) methodof(Web.get_Url)), new ParameterExpression[] { expression }) });
ctx.ExecuteQuery();

Makes perfect sense and should be nice and easy to translate this into PowerShell, right? Yeah, not so much! It’s a major pain and the second example is even worse so I’m not even going to show it here (really, don’t even try to understand what’s going on with that code – it’s not worth it). But all is not lost as I’ve taken the time to do the translation for you, and I even packaged it all up in a nice and easy-to-use function that I called Load-CSOMProperties:

I’m not going to bother you with a detailed analysis of all this code – it’s just too darn confusing and would take away from the point of this article. The thing you need to know is how to use it, so if you were to rewrite the original examples from this article as their PowerShell equivalents, but using this handy dandy new function, you’d get the following:

C:\Scripts\Load-CSOMProperties.ps1

$web = $ctx.Web
Load-CSOMProperties -object $web -propertyNames @("AllProperties", "Url", "Title")
$ctx.ExecuteQuery()

$web = $ctx.Web
Load-CSOMProperties -parentObject $web -collectionObject $web.Fields -propertyNames @("Id", "InternalName") -parentPropertyName "Fields"
$ctx.ExecuteQuery()

Notice that there’s two different ways of calling the function based on whether we’re trying to load properties of an object directly (first example) or if we’re trying to load properties of a child object (second example). For the first example you simply need to provide the object that contains the properties you wish to load along with an array of the property names to load. The second example requires a bit more information to get the job done – specifically, it needs the parent object (the object that contains the collection to load), the collection object itself along with an array list of the properties to load for each item in the collection, and finally, the name of the property associated with the collection object.

I’ve done a reasonable amount of testing with the function and it worked for me without any issues but obviously it’s very complex, and with complexity comes the probability that errors will occur, so use at your own risk.

Summary

PowerShell is an immensely useful tool and you can do amazing things with it from a programming perspective. However, it’s still a bit behind more advanced languages such as C#, so every once in a while you’re likely to come across some C# code that just doesn’t translate easily to PowerShell. In this case, lambda expressions and PowerShell don’t easily mix, but with a little creativity it is possible to hack your way through the gap so that you can still write some reasonably elegant code with the help of a few helper functions. In the article, Completing Basic Operations Using the SharePoint CSOM API and Windows PowerShell, you will get a chance to see how we can use this helper function to assist with the translation from C# to PowerShell of some common MSDN examples. Often times it won’t be necessary to load specific properties and you’ll be content with loading all properties or just one at a time thereby making this hack of a function unnecessary, but it is nice to know that when the situation arises where it is necessary or otherwise beneficial, that you’ve got something like this in your toolbox.


Topic: PowerShell

Sign in with

Or register

  • Thanks a lot.
    Propose to comment '-ne $null' on line 78 like this: if ($collectionObject <#-ne $null#>)
    as it may throw exception in that codeblock ($list is SPList object):
    Get-CsomProperties -object $list -propertyNames @("Title") -executeQuery
    Get-CsomProperties -parentObject $list -collectionObject $list.Fields -propertyNames @("InternalName") -parentPropertyName "Fields" -executeQuery
  • Thank you for this post. The function was just right at the right moment; - =
  • How do I convert the following using Load-CSOM properties?
    CamlQuery camlQuery = CamlQuery.CreateAllItemsQuery();
    ListItemCollection collListItem = list.GetItems(camlQuery);
    context.Load(collListItem, items => items.Include(item => item.Id, item => item.DisplayName, item => item["FileLeafRef"], i =>i["Title"], i=>i.ContentType));