Load fields dynamically when using SharePoint CSOM

The Case

When querying the SharePoint CSOM API:s it is common that you want to fetch specific fields. If you have lots of queries going on toward SharePoint, you should find a way to avoid repetitive code (using the DRY principle) by creating a method that accepts a list of field names to be fetched.

Loading fields dynamically when using GetItems

Usually you will do the follow approach when loading items from a list based on a CAML Query and certain specific fields:

Web web = ctx.Web;
List list = ctx.Web.Lists.GetByTitle(_listNameVitalSignDefinitions);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><RowLimit>500</RowLimit></View>";

ListItemCollection listItems = list.GetItems(camlQuery);

ctx.Load(listItems,
    items => items.Include(
    item => item.Id,
    item => item["Title"],
    item => item["ControlTime"],
    item => item["Description1"]));

await ctx.ExecuteQueryAsync();

To avoid repetitive code, you can creating a generic method that accept the list of field names to be included when querying the GetItems method of the CSOM API. This method can be reused across your application, or even be centralized in your store of reusable components across different applications. In the code below, we have used App Only authentication, but this can of course be replaced with the necessary authentication method for your use case.

public static async Task<ListItemCollection> GetListItemsFromCamlQuery(string siteUrl, string listName, 
    string clientId, string clientSecret, string[] fieldNames, string camlQueryXmlString)
{
    // Create the expression used to define the fields to be included
    List<Expression<Func<ListItemCollection, object>>> fieldsToBeIncluded = 
        new List<Expression<Func<ListItemCollection, object>>>();

    foreach (string s in fieldNames)
    {
        fieldsToBeIncluded.Add(items => items.Include(item => item[s]));
    }

    // Initialize the collection of list items
    ListItemCollection listItems = null;

    // Create a client context, in this case we use an App Only context
    using (var ctx = new AuthenticationManager().GetAppOnlyAuthenticatedContext(siteUrl, clientId, clientSecret))
    {
        try
        {
            // Get the list item from the Price list library
            Web web = ctx.Web;
            List list = ctx.Web.Lists.GetByTitle(listName);
            CamlQuery camlQuery = new CamlQuery();
            camlQuery.ViewXml = camlQueryXmlString;

            listItems = list.GetItems(camlQuery);
            ctx.Load(listItems, fieldsToBeIncluded.ToArray());
            await ctx.ExecuteQueryAsync();
        }
        catch (Exception ex)
        {
            // TODO: Handle and/or log error
            throw ex;
        }
    }
    return listItems;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s