Only load those things you need in CSOM

This is a small post to emphasize why you should only load the things you need with Client Side Object Model for SharePoint. One of the most straightforward reasons to load only what you need is "The amount of data that goes over the wire". Yes, but what about security? If you are loading things you do not need, you might get an unwanted ServerUnauthorizedAccessException.

Consider the following code snippet that is taken from OfficeDevPnP.Core.

public static Folder EnsureFolderPath(this Web web, string webRelativeUrl, params Expression<Func<Folder, object>>[] expressions)
{
  if (webRelativeUrl == null) { throw new ArgumentNullException(nameof(webRelativeUrl)); }

  //Web root folder should be returned if webRelativeUrl is empty
  if (webRelativeUrl.Length != 0 && string.IsNullOrWhiteSpace(webRelativeUrl)) { throw new ArgumentException(CoreResources.FileFolderExtensions_EnsureFolderPath_Folder_URL_is_required_, nameof(webRelativeUrl)); }

  // Check if folder exists
  if (!web.IsPropertyAvailable("ServerRelativeUrl"))
  {
    web.Context.Load(web, w => w.ServerRelativeUrl);
    web.Context.ExecuteQueryRetry();
  }

  var folderServerRelativeUrl = UrlUtility.Combine(web.ServerRelativeUrl, webRelativeUrl, "/");

  // Check if folder is inside a list
  var listCollection = web.Lists;
  web.Context.Load(listCollection, lc => lc.Include(l => l.RootFolder));
  web.Context.ExecuteQueryRetry();

  List containingList = null;

  foreach (var list in listCollection)
  {
    if (folderServerRelativeUrl.StartsWith(UrlUtility.Combine(list.RootFolder.ServerRelativeUrl, "/"), StringComparison.InvariantCultureIgnoreCase))
    {
      // Load fields from the list
      containingList = list;
      break;
    }
  }
  ...
}

Observe that the code is loading the folder for every list, just to use the ServerRelativeUrl. When you execute this method with e.g. App-Only authentication for an app that has Manage on Site Collection. You might get a ServerUnauthorizedAccessException on the ExecuteQueryRetry, which seems kinda strange ... given the fact that the add-in has Manage permissions on Site Collection. Updating the code to only include the ServerRelativeUrl per Folder fixes this nasty Exception.

// Check if folder is inside a list
var listCollection = web.Lists;
web.Context.Load(listCollection, lc => lc.Include(l => l.RootFolder.ServerRelativeUrl));
web.Context.ExecuteQueryRetry();