SharePoint 2010 Client Object Model: Manipulate Choice, Lookup field

After my few posts on Client Object Model, I had come to questions on how to manipulate choice and lookup field. I’ve tried to explain a bit on how you can manipulate these field values with Client Object Model.

Manipulate Choice Field Value (Single Choice)

You can manipulate the single choice field value as like string. For example, let’s consider a field, ProductStatus in Product list. The field values might be “In Stock, Out of Stock, Invalid” as shown below:
image
Figure 1: Single Choice Field (ProductStatus) in product list.
To access the value of the field using Client Object Model, you can use code shown below:
  • Get Field value: You can just get the field value as string
    var productStatus = productItem["ProductStatus"].ToString();
  • Set Field value: You can use any of the following statement to set the field value
    productItem["ProductStatus"] = "In Stock";
    productItem["ProductStatus"] = "Out of Stock";
    productItem["ProductStatus"] = "Invalid";

Manipulate Choice Field Value (Multiple Choice)

If the choice field support multiple values then you need to use string array to manipulate field values. For example, consider there’s a field ‘product types’  in product list whose values can be Foods, electronics, Cars etc. Also consider the field values can be multiple, that’s mean a product types can be more than one type. The following figure shows the field
image
Figure 2: Multiple Choice Field
In that case you need string array to access the multiple choice field value as shown as shown below:
  • Get Field Value:
    var productTypes = (string[]) (productItem["ProductType"]);
  • Set Field Value:
    productItem["ProductType"] = new string[] { "Furniture", "Toys" };

Manipulate Lookup Field Value

To manipulate lookup field you need to use the code as shown below:
  • Get Field Value:
    var lookupFieldValue = (productItem["FieldName"] as FieldLookupValue);
  • Set Field Value
    //100 here is the lookup field id value
    productItem["FieldName"] = new FieldLookupValue(){LookupId = 100};
The FieldLookupValue is part of SharePoint Client OM 

Use ECMAScript to manipulate (Add/Delete/Update/Get) List Items

In SharePoint 2010 there are three different types of Client Object Model extension you can use. They are Managed Client Object Model, ECMAScript and silverlight extension. In one of my post I have described how to manipulate list items using Managed Client Object Model. Today I’ll go through how to use ECMAScrip to manipulate list items. Fist of all make sure your page/webpart is ready to use ECMAScript as I have described inanother post.

How to Get ECMAScript Intellisence

When you’ll use ECMAScript library in Visual Studio, it’s possible to get intellisense for ECMAScript. There are three ways you may need to enable the intellisense:
  1. Get Intellisense in Application Page: In the case you want to put  your javascript in aspx file as inline, you need to add the following lines in the markup file. However, this will not work for webpart file. For webpart file you need to put your javascript in another js file as described in option 2.<script type=”text/ecmascript” src=”/_layouts/SP.debug.js” />
    <script type=”text/ecmascript” src=”/_layouts/SP.Debug.js” />
    <script type=”text/ecmascript” src=”/_layouts/SP.Runtime.Debug.js” />

    <script type=”text/javascript”>
          //you’ll get intellisense here
    </script>
  2. Get Intellisense in js file: If you want to get intellisense in js file then you need to add the following lines in the top of the js file. As shown in the snippet below, the first reference is to MicrosoftAjax.js file. This is mandatory to have this js file reference at the top. Then I have added two other references. The two files (SP.Core.Debug.js and SP.debug.js) have basic SharePoint namespaces. However, if you need more functionalities try to add more js file reference from the path “C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS”
    /// <reference name="MicrosoftAjax.js" />
    /// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.core.debug.js" />
    /// <reference path="file://C:/Program Files/Common Files/Microsoft Shared/Web Server Extensions/14/TEMPLATE/LAYOUTS/SP.debug.js" />
  3. Get Intellisense in webpart: To get intellisense in webpart you need to add the following two lines in the webpart ascx file:
    <script type="text/javascript" src="/_layouts/MicrosoftAjax.js" ></script>
    <script type="text/javascript" src="/_layouts/SP.debug.js" />
    However, I have found the MicrosoftAjax.js file is not located in “/_layouts/MicrosoftAjax.js” and for that the above intellisense will not work. So to get intellisense you need to copy the file in the Layouts folder. You can try to find the MicrosoftAjax.js file from location “C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplatesCache\VisualBasic\Web\1033\EmptyMvcWebApplicationProjectTemplatev2.0.vb.zip\Scripts” if exists. Or you can download the file from the location below where I have uploaded the file: http://cid-04d8f6d0dd4e7214.office.live.com/self.aspx/Public/MicrosoftAjax.js 

A Sample List I have used

For this blog I have used a sample product list with the properties as shown in the following image.
image
Figure 1: Product List

 

Add a new List Item

The code snippet below shows that  you need to get the current SharePoint Context first. Then get the current web from the context. And then you need to get the list from the web. Then I have used ListItemCreationInformation object. There are two important properties of ListItemCreationInforamtion:
  • ListItemCreationInformation.folderUrl: this property defines in which location you want to add the item. The url should start with forward slash(/). For example for the web myweb and list product and for the folder ‘myfolder’ in the product list the url will be ‘/myweb/Lists/product/myfolder’.
  • ListItemCreationInformation.UnderlyingObjectType: this value identity the type of object to create. The possible values are File,Folder, Web and Invalide. The values can be found in ‘SP.FileSystemObjectType’.
The addProduct method below takes few arguments that represents the product list’s fields.
function addProduct(productName, productDesc, productLaunchDate, productAvailQty, productType) {
    try {
        var context = new SP.ClientContext.get_current();        
        var web = context.get_web();
        var list = web.get_lists().getByTitle('product');

        var listItemCreationInfo = new SP.ListItemCreationInformation();
        var newItem = list.addItem(listItemCreationInfo);
        newItem.set_item('Title', productName);
        newItem.set_item('ProductName', productName);
        newItem.set_item('ProductDescription', productDesc);
        newItem.set_item('LaunchDate', productLaunchDate);
        newItem.set_item('AvailableQuantity', productAvailQty);
        newItem.set_item('ProductType', productType);

        newItem.update();
        context.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));
    }
    catch (e) {
        alert('error:' + e.Message);
    }
}
If you look a bit closer in the above code snippet you can find that ClientContext.executeQueryAsync takes two function delegates. The first one will be invoked when the ECMAScript get executed successfully. The second one will be invoked otherwise. The two methods are defined below:
function success() {
    alert('success');
}
function failed(sender, args) {
    alert('failed. Message:' + args.get_message());
}

 

Delete a List Item

To delete a product by product id the following code snippet can be used:
function deleteProduct(productId) {
    var context = new SP.ClientContext.get_current();
    var web = context.get_web();
    var list = web.get_lists().getByTitle('product');
    var itemToDelete = list.getItemById(productId);
    itemToDelete.deleteObject();
    context.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));
}
To delete an object in Client Object Model you need to invoke the deleteObject method of that object.

 

Get Item By Id

To get an item using ECMAScript, you need to share a common variable between the method that execute the ECMAScript (getProductById method in the following code snippet) and callback method (productReceived, failed in the snippet below). Only for this reason I have defined a variable productin the first line of the code snippet below.
var product;
function getProductById(productId) {
    try {
        var context = new SP.ClientContext.get_current();
        var web = context.get_web();
        var list = web.get_lists().getByTitle('product');
        this.product = list.getItemById(productId);
        context.load(product, 'ProductName', 'ProductDescription', 'ProductType', 'LaunchDate', 'AvailableQuantity');
        context.executeQueryAsync(Function.createDelegate(this, this.productReceived), Function.createDelegate(this, this.failed));
    }
    catch (e) {
        alert(e);
    }
}
function productReceived() {
    alert('got product');
    gotProduct(this.product);
}
function failed(sender, args) {
    alert('failed. Message:' + args.get_message());
}
In the code snippet above, the Context.Load method has taken the item to load (product) as the first parameter. And a comma separated list of columns to load for this item are passed then to the load method. If you want to load all properties of the item (which is not recommended) you can just call the context.load method with only first parameter.

Search Items from a List

In the code snippet below Caml Query is used for searching a product by title. I have used Caml Query to search product by title. Notice here that the load takes a second parameter (wrapped with ‘include’) specifying all properties to load for items.
var productcollection;
function getProducts(title) {
    try {
        var context = new SP.ClientContext.get_current();
        var web = context.get_web();
        var list = web.get_lists().getByTitle('product');
        var query = '<View Scope=\'RecursiveAll\'>'+
                        '<Query>'+
                            '<Where>'+
                            '<Contains>'+
                                '<FieldRef Name=\'ProductName\'/>' +
                                '<Value Type=\'Text\'>' + title +'</Value>'+
                            '</Contains>'+
                            '</Where>'+
                        '</Query>'+
                             '</View>';
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml(query);

        this.productcollection = list.getItems(camlQuery);
        context.load(this.productcollection, 'Include(ProductName, ProductDescription, ProductType, LaunchDate, AvailableQuantity)');
        context.executeQueryAsync(Function.createDelegate(this, this.productsReceived), Function.createDelegate(this, this.failed));
    }
    catch (e) {
        alert(e);
    }
}
function productsReceived() {
    alert('got products');
    prcessProducts(this.productcollection);
}
function failed(sender, args) {
    alert('failed. Message:' + args.get_message());
}

 

Update a list item

The code snippet below shows how to update a product item. The list item’s set_item(propertyname, propertyvalue) method is used to update the field values.
function updateProduct(productid, productName, productDesc, productLaunchDate, productAvailQty, productType) {
    var context = new SP.ClientContext.get_current();
    var web = context.get_web();
    var list = web.get_lists().getByTitle('product');
    var product = list.getItemById(productid);
    product.set_item('ProductName', productName);
    product.set_item('ProductDescription', productDesc);
    product.set_item('ProductType', productType);
    product.set_item('LaunchDate', productLaunchDate);
    product.set_item('AvailableQuantity', productAvailQty);
    product.update();
    context.executeQueryAsync(Function.createDelegate(this, this.success), Function.createDelegate(this, this.failed));

}

Points to Remember

1. FormDigest Control: If you write code that modifies data on server, include a FormDigest control to create a digest for security validation of the page. The formdigest control can be added in master page and then all content pages will get it automatically.
<SharePoint:FormDigest runat="server" />
2. Get and Set Property: For the scrip used, when you need to get a property, you need to add get_ as prefix. For example the web has the property title. So if you want to get the title property of web then you need to use the syntax web.get_title(). Similary, if you want to set the title value then you need to invoke web.set_title(‘title’).
2. ClietContext.Load: ClientContext’s load method is used to load object. The first parameter to the load method is the object to load. The second parameter vary depending on whether the first parameter is a single object or collection.
  • If the first parameter is a single object then the following syntax is used to load properties:
context.load(objectToLoad,’property1’,’property2’,………….,’propertyN’)
  • If the first parameter is a collection then the following syntax is used
context.load(objectCollectionToLoad,’Include(property1, property2,……….,propertyN)’)

SharePoint 2010: Attach files to List/Library using Managed Client Object Model

Client Objet Model (OM) is a great new addition in SharePoint 2010. I have discussed before how to manipulate lists and list items using Managed Object Model. Today I’ll discuss on how to attach file to list item or add file to library using Managed Client Object Model.

Upload File in Library

The following code snippet shows how to upload file in document library:
public void UploadFileInLibrary(string siteUrl, string webName, string libraryName, string subfolderPath, string fileName)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {

        string uploadLocation = Path.GetFileName(fileName);
        if (!string.IsNullOrEmpty(subfolderPath))
        {
            uploadLocation = string.Format("{0}/{1}", subfolderPath, uploadLocation);
        }
        uploadLocation = string.Format("/{0}/{1}/{2}", webName, libraryName, uploadLocation);
        var list = clientContext.Web.Lists.GetByTitle(libraryName);
        var fileCreationInformation = new FileCreationInformation();
        fileCreationInformation.Content = System.IO.File.ReadAllBytes(fileName);
        fileCreationInformation.Overwrite = true;
        fileCreationInformation.Url = uploadLocation;
        list.RootFolder.Files.Add(fileCreationInformation);
        clientContext.ExecuteQuery();
    }
}
In the above code snippet, I have constructed the full path to the update location by concatenating the subfolderpath with library location. The site url is the spsite location whereas web name is name of the web site. To upload a file I have use FileCreationInformation object which is part of Client Object Model. To use the above method you can call the method as shown below. The instance is the class instance which has the method. Here the subfolderpath is the folder location inside the library where the document will be uploaded.
Instance.UploadFileInLibrary("http://mysite","mywebname", LibraryName,"folder1/folder2", @"c:\myfiles\LibraryItem.xlsx");

 

Download File From Library

The following code snippets shows how to download file from library:
public void DownloadFileFromLibrary(string siteUrl, string webName, string libraryName, string subfolderPath, string fileName, string downloadPath)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        string filePath = string.Empty;
        if (!string.IsNullOrEmpty(subfolderPath))
        {
            filePath = string.Format("/{0}/{1}/{2}/{3}", webName, libraryName, subfolderPath, fileName);
        }
        else
        {
            filePath = string.Format("/{0}/{1}/{2}", webName, subfolderPath, fileName);
        }

        var fileInformation = File.OpenBinaryDirect(clientContext, filePath);
        var stream = fileInformation.Stream;
        IList<byte> content = new List<byte>();
        int b;
        while ((b = fileInformation.Stream.ReadByte()) != -1)
        {
            content.Add((byte)b);
        }
        var downloadFileName = Path.Combine(downloadPath, fileName);
        System.IO.File.WriteAllBytes(downloadFileName, content.ToArray());
        fileInformation.Stream.Close();
    }
}
As above code shows, we can use Microsoft.SharePoint.Client.File.OpenBinaryDirect method to download file directly from SharePoint. However, SharePoint open the file as binary stream so you need read the full stream before processing the file. The subfolderpath is same as described in ‘Upload File in Library’ section.

Delete File From Library

The following code snippet shows how to delete file from library:
public void DeleteFileFormLibrary(string siteUrl, string webName, string listName, string subfolder, string attachmentFileName)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        string attachmentPath = string.Empty;
        if (string.IsNullOrEmpty(subfolder))
        {
            attachmentPath = string.Format("/{0}/{1}/{2}", webName, listName, Path.GetFileName(attachmentFileName));
        }
        else
        {
            attachmentPath = string.Format("/{0}/{1}/{2}/{3}", webName, listName, subfolder, Path.GetFileName(attachmentFileName));
        }
        var file = clientContext.Web.GetFileByServerRelativeUrl(attachmentPath);
        file.DeleteObject();
        clientContext.ExecuteQuery();
    }
}
As the above code , the DeleteObject method is invoked on file object to delete the file.

Attach File to ListItem

The following code snippet shows how to attach file to list item. The attachments in list are places in a folder whose location is like “http://siteurl/lists/[listname]/Attachments/[ListItemID]/[filename]”. So I have constructed the attchment location first and use Microsoft.SharePoint.Client.File.SaveBinaryDirect method to upload the file. Here in the method, Item id is the list item id that I want to attach the file to.
public void AttachFileToListItem(string siteUrl, string webName, string listName, int itemId, string fileName, bool overwrite)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        FileStream fileStream = new FileStream(fileName, FileMode.Open);
        string attachmentPath = string.Format("/{0}/Lists/{1}/Attachments/{2}/{3}", webName, listName, itemId, Path.GetFileName(fileName));
        File.SaveBinaryDirect(clientContext, attachmentPath, fileStream, overwrite);
    }
}

 

Download File from ListItem

The following code snippet shows how to download file that is attached with list item.
public void DownloadAttachedFileFromListItem(string siteUrl, string webName, int itemId, string attachmentName, string listName, string downloadLocation)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        string attachmentPath = string.Format("/{0}/lists/{1}/Attachments/{2}/{3}", webName, listName, itemId, Path.GetFileName(attachmentName));
        var fileInformation = File.OpenBinaryDirect(clientContext, attachmentPath);
        IList<byte> content = new List<byte>();
        int b;
        while ((b = fileInformation.Stream.ReadByte()) != -1)
        {
            content.Add((byte)b);
        }
        var downloadFileName = Path.Combine(downloadLocation, attachmentName);
        System.IO.File.WriteAllBytes(downloadFileName, content.ToArray());
        fileInformation.Stream.Close();
    }
}
As said before, the attachment location is “http://siteurl/lists/[listname]/Attachments/[itemid]/[filename]”. So I have used Microsoft.SharePoint.Client.File.OpenBinraryDirect to download the file.

Delete Attached File From ListItem

The following code shows how to delete a file that is attached with list item.
public void DeleteAttachedFileFromListItem(string siteUrl, string webName, int itemId, string attachmentFileName, string listName)
{
    using (ClientContext clientContext = new ClientContext(siteUrl))
    {
        //http://siteurl/lists/[listname]/attachments/[itemid]/[filename]
        string attachmentPath = string.Format("/{0}/lists/{1}/Attachments/{2}/{3}", webName, listName, itemId, Path.GetFileName(attachmentFileName));
        var file = clientContext.Web.GetFileByServerRelativeUrl(attachmentPath);
        file.DeleteObject();
        clientContext.ExecuteQuery();
    }
}

Conclusion

The code snippet above just provide you the gist. One point to notice that the File class used in the code not from System.IO. This is from Microsoft.SharePoint.Client and the full name is “Microsoft.SharePoint.Client.File”.

SharePoint 2010: Add/Delete/update/search list items with Managed Client Object Model

Managed client Object model is a rich extension to SharePoint 2010. You can almost perform all kinds operations against SharePoint using Client OM. In this post I’ll show you how to use Managed client Object Model (OM) to manipulate list items. The code snippet I’ll use in the examples below is depend on a product list. The product list has four fields: Product Name, Product Description, Product launch date, available quantity. The product list is represented with a class as shown below:
public class Product
{
    public string ProductName { get; set; }
    public int ProductID { get; set; }
    public string ProductDescription { get; set; }
    public DateTime LaunchDate { get; set; }
    public int AvailableQuantity { get; set; }
}

Add new list item

To add a new item in a list you may or may not need to pass ListItemCreationInformation.  Let me explain when you need to pass ListItemCreationInformation or when not:
  • If you need to add item at the root (not under a subfolder) then you can ignore ListItemCreationInformation by passing null in place of ListItemCreationInformation.
  • If you need to add item somewhere inside subfolder then you need to create an instance of ListItemCreationInformation and set it’s Folderurl to url of the folder you want to save the list item.
The code snippet below add a new list item (Product item in my case):
public void AddNewProduct(string siteUrl, string folderPath, Product product)
{
    const string listName = "Product";
    using (var clientContext = new ClientContext(siteUrl))
    {
        var list = clientContext.Web.Lists.GetByTitle("Product");

        ListItemCreationInformation listItemCreationInformation = null;
        if (!string.IsNullOrEmpty(folderPath))
        {
            listItemCreationInformation = new ListItemCreationInformation();
            listItemCreationInformation.FolderUrl = string.Format("{0}/lists/{1}/{2}", siteUrl, listName, folderPath);
        }

        var listItem = list.AddItem(listItemCreationInformation);
        listItem["ProductName"] = product.ProductName;
        listItem["ProductDescription"] = product.ProductDescription;
        listItem["LaunchDate"] = product.LaunchDate;
        listItem["AvailableQuantity"] = product.AvailableQuantity;
        listItem.Update();
        clientContext.ExecuteQuery();

    }
}
The method in above code snippet takes a site url  and optional folder url and a product. If you want to add item in the root folder then you can pass folderPath parameter empty or null in the above method. Depending on whether you have passed folderPath or not, the ListItemCreationInformation will be initialized or not. If you don’t pass folderPath, the ListItemCreationInformation variable will be null. but if you want to add item in a specific subfolder then pass the folder name as parameter and the ListItemCreationInformation will be initialized and teh FolderUrl of the instance will be set with parameter folderaPath.

Delete list item

In the code snippet below, I have used the same product list. I have passed the product Id as parameter and the get the list item by id. Once I get the list item, I have invoked the DeleteObject method of the list item.
public void DeleteProduct(string siteUrl, int productId)
{
    using (var clientContext = new ClientContext(siteUrl))
    {
        var list = clientContext.Web.Lists.GetByTitle("Product");
        var product = list.GetItemById(productId);
        product.DeleteObject();
        clientContext.ExecuteQuery();
    }
}

Update List Item

The following code snippet shows how to update a product list.
public void UpdateProduct(string siteUrl, Product product)
{
    using (var clientContext = new ClientContext(siteUrl))
    {
        var list = clientContext.Web.Lists.GetByTitle("Product");
        var productToModify = list.GetItemById(product.ProductID);
        productToModify["ProductName"] = product.ProductName;
        productToModify["ProductDescription"] = product.ProductDescription;
        productToModify["LaunchDate"] = product.LaunchDate;
        productToModify["AvailableQuantity"] = product.AvailableQuantity;
        productToModify.Update();
        clientContext.ExecuteQuery();
    }
}

Get a single List Item

To get a lsit item you need to specify the fields you want to retrieve from the list item.
public Product GetProductById(string siteUrl, int productId)
{
    Product product = null;
    try
    {

        using (var clientContext = new ClientContext(siteUrl))
        {
            var list = clientContext.Web.Lists.GetByTitle("Product");
            var productItem = list.GetItemById(productId);
            clientContext.Load(productItem, pi => pi.Id, pi => pi["ProductName"], pi => pi["ProductDescription"], pi => pi["AvailableQuantity"], pi => pi["LaunchDate"]);
            clientContext.ExecuteQuery();
            product = new Product();
            product.AvailableQuantity = Convert.ToInt32(productItem["AvailableQuantity"]);
            product.LaunchDate = Convert.ToDateTime(productItem["LaunchDate"]);
            product.ProductDescription = productItem["ProductDescription"].ToString();
            product.ProductID = productItem.Id;
            product.ProductName = productItem["ProductName"].ToString();
        }
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);

    }
    return product;
}
As shown in the example below, the field values I like to retrieve are passed in the ClientContext.Load method. If you want to retrive all fields (which is not recommended) then call the Load method with the list item, as shown below:
clientContext.Load(productItem);

Get Collection of List Items

To get a list of items as per any condition, you can use CAML  query (or in Linq to SharePoint extension). I’ve covered in another post on how to use Linq to SharePoint. One important point to notice here in the code snippet below is that if you want to look for items inside subfolders thenyou need to add an extra attribute Scope=’RecursiveAll’ in view tag.
public IList<Product> FindProductsByName(string siteUrl, string productName, bool includeSubfolder)
{
    IList<Product> products = new List<Product>();
    try
    {
        string scope = string.Empty;
        if (includeSubfolder)
        {
            scope = "Scope='RecursiveAll'";
        }

        using (var clientContext = new ClientContext(siteUrl))
        {
            List list = clientContext.Web.Lists.GetByTitle("Product");
            CamlQuery query = new CamlQuery();
            query.ViewXml = string.Format(@"<View {0}>
                                <Query>
                                    <Where>
                                    <Contains>
                                        <FieldRef Name='ProductName'/>
                                        <Value Type='Text'>{1}</Value>
                                    </Contains>
                                    </Where>
                                </Query>
                                </View>", scope, productName);
            ListItemCollection listItems = list.GetItems(query);
            clientContext.Load(listItems, li => li.Include(pi => pi.Id, pi => pi["ProductName"], pi => pi["ProductDescription"], pi => pi["AvailableQuantity"], pi => pi["LaunchDate"]));
            clientContext.ExecuteQuery();

            foreach (var productItem in listItems)
            {
                var product = new Product();
                product.AvailableQuantity = Convert.ToInt32(productItem["AvailableQuantity"]);
                product.LaunchDate = Convert.ToDateTime(productItem["LaunchDate"]);
                product.ProductDescription = productItem["ProductDescription"].ToString();
                product.ProductID = productItem.Id;
                product.ProductName = productItem["ProductName"].ToString();
                products.Add(product);
            }
        }
    }
    catch (Exception exception)
    {
        Console.WriteLine(exception.Message);

    }
    return products;
}
You can notice that I have passed the fields I want to load as per the query result in ClientContext.Load’s li.Include extension method. If you want to load all properties then you can call the Load method in a way as shown below:
clientContext.Load(listItems, li => li);

If you don’t specify a field to load but try to access it then you will get an exception of type ‘PropertyOrFieldNotInitializedException’ with the following message:
The property or field has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.