Blog

Sharepoint Rest Caml Query

On 06/01/2021

Use Sharepoint REST api to do a caml query

 


fdi.post = function(request, data, urlWeb, retFunction, expecedcode=200, odata="verbose"){
    var url = _spPageContextInfo.webAbsoluteUrl + "/_api/contextinfo?&select=FormDigestValue";
	var xhr = new XMLHttpRequest();
	xhr.open('POST', url, true);
	xhr.setRequestHeader("Accept", "application/json; odata=nometadata");
	xhr.onload = function (data) {
		if (xhr.status === 200) {
			console.log(url + " : success");
			var d = JSON.parse(xhr.responseText);
            console.dir(d.FormDigestValue);

            var viewXml =  "<View>" +
                    "<Query>" +
                    "<Where></Where>" +
                    "</Query>" +
                    "</View>";
            
            var req = { "query" :{"__metadata": { "type": "SP.CamlQuery" }, "ViewXml": viewXml}};
            var xhrPOST = new XMLHttpRequest();
            var reqUrl = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/GetByTitle('Catalogue Produits')/GetItems";
            debugger;
            xhrPOST.open('POST', reqUrl, true);
            xhrPOST.setRequestHeader("Accept", "application/json; odata=" + odata);
            xhrPOST.setRequestHeader("content-type", "application/json; odata=" + odata);
            xhrPOST.setRequestHeader("X-RequestDigest", d.FormDigestValue);

            console.log("onload");
            xhrPOST.onload = function () {
                
            console.log("onload ok");
                console.dir(JSON.parse(xhrPOST.responseText));
            }
            xhrPOST.send(JSON.stringify(req));
            console.log("sent");
		}
		else {
			console.log("error");
			console.log(xhr.status);
			console.dir(xhr);
			console.dir(xhr.responseText);			
		}
	};
    xhr.send();
};

SPLoaderError.loadComponentError

On 09/12/2020

SPFX react sur Internet explorer : [SPLoaderError.loadComponentError]: There was a network problem. This may be a problem with a HTTPS certificate. Make sure you have the right certificate.

 

It's not always à certificate error, in my case, i use code below in a service,

 


import 'core-js/modules/es6.string.includes.js';//in my case this line should be commented to fix the isssue
import 'core-js/modules/es6.number.is-nan.js';
import 'core-js/es6/array';
import 'es6-map/implement';

when including "@types/es6-promise": "^3.3.0" i don't need anymore import 'core-js/modules/es6.string.includes.js

Sharepoint Online Missing Icons

On 09/12/2020

Sharepoint missing icon on SPFX developpements

 

Some ican can be missing per exemple on :

SPFX missing icon as <i data-icon-name="Tag" class="ms-Button-icon icon-167" role="presentation" aria-hidden="true"></i> 

So you simply have to add this code below after yours imports

 


import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';

initializeIcons();

 

Sharepoint Modern Update listItem

On 09/12/2020

Update list in a modern site, getting formDigestValue


console.clear();
var dataToManage = {};
function getItemTypeForListName(listTitle, returnfct){
	var xhr = new XMLHttpRequest();
	var url = _spPageContextInfo.webAbsoluteUrl;
	if (url === "undefined") {
		console.log("_spPageContextInfo.webAbsoluteUrl undefined");
		url = "http://siteUrl";
	}
	
	xhr.open('GET', url + "/_api/web/lists/getbytitle('" + listTitle + "')/?$select=ListItemEntityTypeFullName");
	xhr.setRequestHeader("Accept", "application/json; odata=verbose");
	xhr.onload = function () {
		if (xhr.status === 200) {
			var kk = JSON.parse(xhr.responseText);
			console.dir(kk.d.ListItemEntityTypeFullName);
                        var returnValue = {};
			returnValue.ListItemEntityTypeFullName = kk.d.ListItemEntityTypeFullName;
			if(returnfct != null)
				returnfct(returnValue);
		}
		else {
			console.dir(xhr);
			alert('Request failed.  Returned status of ' + xhr.status);
		}
	};
	xhr.send();
}

//get FormDigestValue to do POST requests
function GetDisgestValue(returnFct){
    var url = _spPageContextInfo.webAbsoluteUrl + "/_api/contextinfo";
	var xhr = new XMLHttpRequest();
	xhr.open('POST', url, true);
	xhr.setRequestHeader("Accept", "application/json; odata=verbose");
	xhr.setRequestHeader("content-type", "application/json; odata=verbose");
	xhr.onload = function (data) {
		if (xhr.status === 200) {
			console.log("success");
			var d = JSON.parse(xhr.responseText);
			console.dir(d.d.GetContextWebInformation.FormDigestValue);
			dataToManage.FormDigestValue = d.d.GetContextWebInformation.FormDigestValue;
			returnFct(d.d.GetContextWebInformation.FormDigestValue);
		}
		else {
			console.log("error");
			console.log(xhr.status);
			console.dir(xhr);
			console.dir(xhr.responseText);			
		}
	};
	xhr.send();
}

function UpdateListItem(){
	
    var url = _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle" + 
	"('" + dataToManage.listName + "')/items("+dataToManage.itemId+")";
	
	var xhr = new XMLHttpRequest();
	xhr.open('POST', url, true);
	xhr.setRequestHeader("Accept", "application/json; odata=verbose");
	xhr.setRequestHeader("X-RequestDigest", dataToManage.FormDigestValue );
	xhr.setRequestHeader("content-type", "application/json; odata=verbose");
	xhr.setRequestHeader("X-HTTP-Method", "MERGE");
	xhr.setRequestHeader("If-Match", "*");
	
	xhr.onload = function () {
		if (xhr.status === 204) {
			console.log("success");
		}
		else {
			console.log("error");
			console.log(xhr.status);
			console.dir(xhr);
			console.dir(xhr.responseText);
			
		}
	};
	var str = JSON.stringify(dataToManage.item);
	xhr.send(str);
} 

function withDigestValue(formDigestValue){
	console.log("formDigestValue : " + formDigestValue);	
}

function getListDatas(data){
	console.log(data.ListItemEntityTypeFullName);
	dataToManage.listName = "aTest";//list title to update
	dataToManage.itemId = 1;//id of the item to update
	dataToManage.item = {
        "__metadata": { "type": data.ListItemEntityTypeFullName },
		"Title": "new title"//new fields values
    };
	GetDisgestValue(UpdateListItem);
}

getItemTypeForListName("atest", getListDatas);

In SQL

Sharepoint Caml Query

On 08/09/2020

Basic CSOM caml query

 

<View>
    <Query>
        <Where>
            <Eq>
                <FieldRef Name='Matricule'/>
                <Value Type='Text'>90136794</Value>
            </Eq>
        </Where>

<OrderBy><FieldRef Name='ID' Ascending='True'/></OrderBy>
    </Query>
    <ViewFields>
        <FieldRef Name='Matricule' />
        <FieldRef Name='Email' />
    </ViewFields>
    <RowLimit>2</RowLimit>
</View>

 

Query Null Text fields or not

<Where>
    <IsNotNull>
        <FieldRef Name="Famille"/>
    </IsNotNull>
</Where>


<Where>
    <IsNull>
        <FieldRef Name="Famille"/>
    </IsNull>
</Where>

 

by ID

<Where>
    <Eq>
        <FieldRef Name='ID'/>
        <Value Type='Counter'>645</Value>
    </Eq>
</Where>

 

Get tasks by itemId (relatedItems in tasks list)

<Where>
    <Eq>
        <FieldRef Name='RelatedItems'/>
        <Value Type='RelatedItems'>""ItemId"":435,</Value>
    </Eq>
</Where>

 

boolean / Yes/No

<Eq><FieldRef Name='YourFieldName'/><Value Type='Boolean'>1</Value></Eq>

 

Comparators

<Eq> => equals

<Neq> => not equals

<Lt> => Less than

<Leq> => less or equal

<Gt> greater than

<Geq> greater or equal

<Contains>

<BeginsWith>

 

Errors

  • Sharepoint error Error in my cases
    One or more field types are not installed properly. Go to the list settings page to delete these fields. Fields in your query are not in list

    Cannot complete this action.

    Please try again.

    Syntax error in your query
       
       
       
       
       
       
       

     

SPFX React Tips

On 02/09/2020

Override native css

 

:global(#spLeftNav) {  
  display: none;
} 
:global(.CanvasZone) {  
  max-width: 100%;
} 

Is member of

import 'core-js/modules/es6.string.includes.js';
import 'core-js/modules/es6.number.is-nan.js';
import 'core-js/es6/array';
import 'es6-map/implement';
import { sp,SPRest } from '@pnp/sp';
import { IWebPartContext } from '@microsoft/sp-webpart-base';
import * as React from 'react';

class PeopleService {
    private _context: IWebPartContext;
    private _localPnPSetup: SPRest;

    public constructor(webPartContext: IWebPartContext) {
        this._context = webPartContext;

        // To limit the payload size, we set odata=nometadata
        // We just need to get list items here
        // We use a local configuration to avoid conflicts with other Web Parts
        this._localPnPSetup = sp.configure({
            headers: {
                Accept: 'application/json; odata=nometadata',
            },
        }, this._context.pageContext.web.absoluteUrl);
    }

    public async isMemberOf(group: string): Promise{
        let groups = await this._localPnPSetup.web.currentUser.groups.get();
        let ret: boolean = false;
        
        groups.map(grp =>{
            if(grp.LoginName == group)
            ret =  true;
        });
        return ret;
    }

    public async isMemberOfanyGroup(groupNames: string[]): Promise{
        let groups = await this._localPnPSetup.web.currentUser.groups.get();
        let ret: boolean = false;
        groups.map(grp =>{
            groupNames.map(name =>{
                console.log("name : '" + name + "' grp : '" + grp.LoginName  + "'");
            if(grp.LoginName == name)
                ret = true;
            });
        });
        return ret;
    }

}
export default PeopleService;

Taxonomy, get tags, add tags

import { IWebPartContext } from '@microsoft/sp-webpart-base';
import { Session, ITermStore, ITermSet, ITermData, ITerm } from '@pnp/sp-taxonomy';

class TaxonomyService {
    private _context: IWebPartContext;
    
    public constructor(webPartContext: IWebPartContext) {
        this._context = webPartContext;
    }

    public async getTags() : Promise{
        
        console.log("Session");
        const taxonomy = new Session(this._context.pageContext.site.absoluteUrl);
        const store: any = taxonomy.termStores.getByName("Taxonomy_Wf8XzHaRobdAERjvvke+Tg==");
        let datas = await store.getTermSetById("c18ff3e6-e4a8-4dcb-85f5-51171f4bbc11").terms.select('Name', 'Id', 'Parent').get();
        
        let ret: string[] = [];
        for(let i = 0 ; i < datas.length ; i++)
            ret.push(datas[i]);

        return datas;
    }
    
    public async addNewTag(tag){
        
        const taxonomy = new Session(this._context.pageContext.site.absoluteUrl);
        const store: any = taxonomy.termStores.getByName("Taxonomy_Wf8XzHaRobdAERjvvke+Tg==");
        let datas = await store.getTermSetById("c18ff3e6-e4a8-4dcb-85f5-51171f4bbc11");
        const term: ITerm & ITermData = await datas.addTerm(tag, 1036, true);
    }
}
export default TaxonomyService;

CSOM Delete Items By Id Range

On 02/09/2020

CSOM delete items by id range

Get items

public ListItemCollection GetItems(string listRelativUrl, string where, string orderBy, string viewFields, int rowlimit = 100)
{
    string xmlView = "";
    try
    {
        List lst = CurrentWeb.GetList(CurrentWeb.ServerRelativeUrl + listRelativUrl);

        StringBuilder vf = new StringBuilder();
        if (!string.IsNullOrEmpty(viewFields))
        {
            vf.Append("<ViewFields>");
            foreach (string fieldName in viewFields.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
            {
                vf.Append($"<FieldRef Name='{fieldName.Trim()}' />");
            }

            vf.Append("</ViewFields>");
        }

        CamlQuery camlQuery = new CamlQuery();
        camlQuery = new CamlQuery();
        Logger.LogInfo($"listRelativUrl {listRelativUrl} : <View><Query>{where}{orderBy}</Query>{vf.ToString()}<RowLimit>{rowlimit}</RowLimit></View>");
        xmlView = $"<View><Query>{where}{orderBy}</Query>{vf.ToString()}<RowLimit>{rowlimit}</RowLimit></View>";
        camlQuery.ViewXml = xmlView;

        ListItemCollection coll = lst.GetItems(camlQuery);
        SPContext.Load(coll);
        SPContext.ExecuteQuery();

        Logger.Log($"coll.Count : '{coll.Count}' : camlQuery.ViewXml {camlQuery.ViewXml}");

        return coll;
    }
    catch (ServerException ex1)
    {
        Logger.LogError($"Error ServerException Common.Sharepoint.SPTools.GetItems url '{_url}' login : '{_login}' " +
            $" listRelativUrl '{listRelativUrl}' where '{where}' orderBy '{orderBy}' rowlimit '{rowlimit}' xmlView : '{xmlView}' Exception '{ex1}'");
        throw;
    }
    catch (Exception ex)
    {
        Logger.LogError($"Error .Common.Sharepoint.SPTools.GetItems url '{_url}' login : '{_login}' " +
            $" listRelativUrl '{listRelativUrl}' where '{where}' orderBy '{orderBy}' rowlimit '{rowlimit}' xmlView : '{xmlView}' Exception '{ex}'");
        throw;
    }
}

delete items


public int DeleteItemByIdRange(string listRelativeUrl, int rowLimit, int from, int to = -1)
{
    int deleted = 0;
    try
    {
        string req = "";
        if (to == -1)
            req = $"<Where><Geq><FieldRef Name='ID'/><Value Type='Counter'>{from}</Value></Geq></Where>";
        else
        {
            if (from > to)
                throw new Exception($"DeleteItemByIdRange from should be < than to listRelativeUrl '{listRelativeUrl}' from '{from}' to '{to}'");
            req = $"<Where><And><Geq><FieldRef Name='ID' /><Value Type='Counter'>{from}</Value></Geq><Leq><FieldRef Name='ID' /><Value Type='Counter'>{to}</Value></Leq></And></Where>";
        }
        ListItemCollection coll = GetItems(listRelativeUrl, req, "", "ID", rowLimit);

        while (coll.Count > 0)
        {
            string id = coll[0].Id.ToString();
            coll[0].DeleteObject();
            this.ExecuteQuery($"DeleteItemByIdRange listRelativeUrl '{listRelativeUrl}' from '{from}' to '{to}' Id = '{id}'");
            deleted++;
        }
        return deleted;
    }
    catch (Exception ex)
    {
        Logger.LogError($"Error Sharepoint.SPTools.DeleteItemByIdRange from id '{from}' to id '{to}' url '{_url}' login : '{_login}'  Exception '{ex}'");
        throw;
    }
}

catch ServerException to get more details on CSOM exceptions

Invalid Client Query Exception

On 07/07/2020

Microsoft.SharePoint.Client.InvalidClientQueryException A type named 'SP.Data' could not be resolved by the model. When a model is available, each type name must resolve to a valid type

 

get the correct ListItemEntityTypeFullName 

 

 




var xhr = new XMLHttpRequest();
var url = _spPageContextInfo.webAbsoluteUrl;
if (url === "undefined") {
    console.log("_spPageContextInfo.webAbsoluteUrl undefined");
    url = "http://siteUrl";
}
//xhr.open('GET', url +"/_api/web/Lists?$select=Id,Title,Hidden,ItemCount");
xhr.open('GET', url + "/_api/lists/getbytitle('Campaigns')?$select=ListItemEntityTypeFullName");
xhr.setRequestHeader("Accept", "application/json; odata=verbose");
xhr.onload = function () {
    if (xhr.status === 200) {
        var kk = JSON.parse(xhr.responseText);
        console.dir(kk);
    }
    else {
        console.dir(xhr);
        alert('Request failed.  Returned status of ' + xhr.status);
    }
};
xhr.send();