Partager via


Troubleshoot issues with SharePoint hosted Add-ins

This post is a contribution from Jing Wang, an engineer with the SharePoint Developer Support team

SharePoint Hosted Add-ins are hosted inside SharePoint environment. They use SharePoint JSOM code (JavaScript Object Model) to access list/library items in add-in web or Host web.

They can contain SharePoint lists, Web Parts, workflows, custom pages, and other components, which are usually installed on a subweb, called the add-in web, of the Host SharePoint website where the add-in is installed.

Here are some common issues customers encountered for SharePoint hosted Add-ins:

Sharepoint hosted app not working after publish

The Sharepoint hosted add-in works okay when deploy with F5 from Visual Studio, but after publish and add it to App Catalog, if you try to add it to Site, you get an error : “The page can't be displayed, make sure web address is correct”,

Sometimes, the error is:

Fiddler trace shows the following.

The cause of this is the app’s URL cannot be resolved with DNS.
The solution is to set up the app domain in DNS and creating a forward lookup zone and a CNAME alias (because each app web's URL will contain a unique hash). These steps are described in detail in this TechNet article

 

Problems when host site’s Web Application is Host Header Web Application:

There are various kinds of symptoms of this category, for example,

a. 404 Not Found

Fiddler trace shows the following.

b. Blank page

c. HTTP 403 Forbidden:

In IE:

In Chrome:

d. Multiple Line of Text field in Add-in web (app web) is blank in form pages:

If the Add-in works in a non-host header web application, verify following configurations:

1. A SharePoint Web Application without host header on default port (80 or 443 depending on whether the hosting web application is on SSL or not).
I will call this Web Application “PlaceHolder Web Application” in this article.

2. PlaceHolder Web Application needs to have a root site collection.

3. If you have setup separate app domain for Add-ins, for example, apps.com, the certificate on your non PlaceHolder Web Application must also have a wildcard for your app domain (*.apps.com).

4. PlaceHolder Web Application’s Application Pool account needs to be same as Host Header Web Application’s Application Pool account.

If they are not the same, change the service account on Central Admin –> Security –> Configure service accounts:

 

Cannot access list/list items in Host Web with JSOM code:

To access list/list items in Host Web:

  • Request permission to the host web in the add-in manifest file of your add-in. The user who installs the add-in is prompted to grant this permission, and the add-in cannot be installed if the user does not.
  • Instead of using an SP.ClientContextobject to make JSOM calls to the host web, you use an SP.AppContextSite object. This object enables the add-in to get a context object for websites other than the add-in web, but only for websites within the same site collection.

Sample code:

App.js:
----------

 'use strict'; 
ExecuteOrDelayUntilScriptLoaded(initializePage, "sp.js"); 
function initializePage()
{
    var context = SP.ClientContext.get_current();
    var user = context.get_web().get_currentUser();
    var hostWebUrl;
    var appWebUrl;
    var listName = "testList";  
    var ctx;
    var appCtxSite;
    var oList;
    var web;
    var collListItem;  
    // This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
    $(document).ready(function () {         
        hostWebUrl = decodeURIComponent(getQueryStringParameter('SPHostUrl'));
        appWebUrl = decodeURIComponent(getQueryStringParameter('SPAppWebUrl'));
        getListItemFromHostWeb(); 
    }); 
    //get the list data from host web  
    function getListItemFromHostWeb() {
        debugger;
        ctx = new SP.ClientContext(appWebUrl);
        appCtxSite = new SP.AppContextSite(ctx, hostWebUrl);
        oList = appCtxSite.get_web().get_lists().getByTitle(listName); 
        ctx.load(oList);
        ctx.executeQueryAsync(oListExist, OnGetListItemFailure);
    } 
    //check whether list is exist or not  
    function oListExist(sender, args) {        
        alert('Got List Title - ' + oList.get_title());
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml('<View><Query><Where><Geq><FieldRef Name=\'ID\'/>' +
            '<Value Type=\'Number\'>1</Value></Geq></Where></Query><RowLimit>10</RowLimit></View>');
        collListItem = oList.getItems(camlQuery);        
        ctx.load(collListItem);
        ctx.executeQueryAsync(onGetListItemSucceeded, OnGetListItemFailure);     
    }
 
    function onGetListItemSucceeded(sender, args) {        
        var listItemInfo = '<p>';
        var listItemEnumerator = collListItem.getEnumerator();
        if (collListItem.get_count() > 0) {
            while (listItemEnumerator.moveNext()) {
                var oListItem = listItemEnumerator.get_current();
                listItemInfo += oListItem.get_id() + ',Title: ' + oListItem.get_item('Title');
            }
            listItemInfo += '</p>';            
            document.getElementById('Label1').innerHTML = listItemInfo.toString();
        }
    }    
 
    function OnGetListItemFailure(sender, args) {
        alert('Failed to get target List. Error:' + args.get_message());
    } 
    //This function is used to get the hostweb url  
    function getQueryStringParameter(paramToRetrieve)   
    {  
        var params =  
        document.URL.split("?")[1].split("&");  
        var strParams = "";  
        for (var i = 0; i < params.length; i = i + 1)  
        {  
            var singleParam = params[i].split("=");  
            if (singleParam[0] == paramToRetrieve)   
               { return singleParam[1]; }  
        }  
    }       
}