J’ai récemment créer une petite application Sharepoint qui servira de tableau de bord sur un site hôte. J’ai donc besoin d’accéder à plusieurs informations du site dans mon application comme la liste des sous-sites, la liste des documents, etc..

Pour cela, mon application utilise l’API Javascript qui fait un appel à distance vers Sharepoint.  Plusieurs exemples sont déjà disponibles en ligne pour apprendre à créer son application avec Javascript. Le point qui a été un peu complexe à trouver dans mon cas est de faire des appels vers l’hôte Sharepoint en « Cross-domain ».

En effet, à la base, mon application est assez indépendant du site Sharepoint hôte et je n’ai pas accès à toutes les données dès le départ. Dans mon exemple, j’essaie de récupérer les sous-sites du site hôte avec un code très simple :

    // Charge les sous-sites 
    web = appContextSite.get_web(); 
    subsites = web.getSubwebsForCurrentUser(null); 
    context.load(subsites) 
    context.executeQueryAsync(ExecuteOnSubSitesSuccess, ExecuteOnSubSitesFailure);

C’est la fonction getSubwebsForCurrentUser qui fait le gros du travail pour récupérer la liste des sous-sites. Le problème que j’ai rencontré est que même si le site hôte a bien plusieurs sous-site, cette fonction retourne une liste vide.

Il m’a fallu un peu de temps pour comprendre qu’en fait, dans ce cas simple, ce code va retourner la liste des sous-sites de mon application et non de ceux du site hôte!

Pour pouvoir lire ces informations du site hôte, il y a quelques modification à faire dans le script et il faut charger un fichier JS qui va permettre de faire des requêtes à distance sur le site hôte. Je charge donc le fichier SP.RequestExecutor.js avant de lancer la requête:

ExecuteOrDelayUntilScriptLoaded(LoadHostConfiguration, "sp.js"); 
//Get host configuration 
function LoadHostConfiguration() { 
    //Récupération des URL de l'hote et de l'appli 
    hostweburl = 
        decodeURIComponent( 
            getQueryStringParameter("SPHostUrl") 
    ); 
    appweburl = 
        decodeURIComponent( 
            getQueryStringParameter("SPAppWebUrl") 
    ); 
 
    // Get file from ressources path:  
    // web_url/_layouts/15/resource  
    var scriptbase = hostweburl + "/_layouts/15/"; 
 
    // Load js file for cross-domain request 
    $.getScript(scriptbase + "SP.RequestExecutor.js", GetSubSites); 
}

Enfin, je crée la fonction qui permet de récupérer les sous-sites une fois le fichier SP.RequestExecutor.js chargé : 

function GetSubSites() { 
    context = new SP.ClientContext(appweburl); 
    var factory = SP.ProxyWebRequestExecutorFactory(appweburl); 
    context.set_webRequestExecutorFactory(factory); 
    var appContextSite = new SP.AppContextSite(context, hostweburl); 
    web = appContextSite.get_web(); 
    subsites = web.getSubwebsForCurrentUser(null); 
    context.load(subsites) 
    context.executeQueryAsync(ExecuteOnSubSitesSuccess, ExecuteOnSubSitesFailure); 
}

J’ai encore beaucoup à apprendre sur les best-practices des applications Sharepoint et j’ai publié un sample sur Office Dev Center afin d’avoir des retours de la communauté et continuer à améliorer ce code.