Export (0) Print
Expand All

How to: Access SharePoint 2013 data from apps using the cross-domain library

apps for SharePoint

Learn how to access data in a SharePoint website from your app by using the cross domain library in SharePoint 2013.

Last modified: May 11, 2014

Applies to: apps for SharePoint | Office 365 | SharePoint Foundation 2013 | SharePoint Server 2013

In this article
Prerequisites for using the examples in this article
Read data on the app web using the cross-domain library
Next steps
Additional resources

When you build apps for SharePoint, you usually have to incorporate data from various sources. But for security reasons, there are blocking mechanisms that prevent communication with more than one domain at a time. These security mechanisms are implemented in most browsers, making difficult or impossible to accomplish client-side calls across domains.

Figure 1 shows a blocked request across domains.

Figure 1. Blocked request across domains

Blocked request across domains

When a user requests a page from your app domain (1), the client-side communication is bound only to that domain. Your app can issue client-side calls from the page only to other resources in the same domain. However, apps usually require resources from other domains, such as the SharePoint domain, to fulfill their scenarios. In the code in your page, you may try to issue a request to the SharePoint domain (2), which is blocked by the browser. You usually see an Access is denied error. The error doesn’t imply that you don’t have permissions to the requested resources but, most likely, you can’t even issue a request to the mentioned resources.

When you use the cross-domain library, the webpages in your app can access data in your app domain and the SharePoint domain. The cross-domain library is a client-side alternative in the form of a JavaScript file (SP.RequestExecutor.js) that is hosted in the SharePoint website that you can reference in your remote app. The cross-domain library lets you interact with more than one domain in your remote app page through a proxy. It is a good option if you like your app code to run on the client instead of on the server, and if there are connectivity barriers, such as firewalls, between SharePoint and your remote infrastructure. You can access data in the host web—for example, you can access lists that end users interact with regardless of your app. Or you can access data in the app web, such as lists specifically provisioned for your app. Apps can also access other site collections and websites as long as the app has tenant-scoped permissions and it has been deployed as a batch installation using the app catalog.

Note Note

In this topic, app domain refers to the domain that hosts the app pages. This can be the domain of a remote web application in a provider-hosted, but app pages can also be on SharePoint in the app web and make calls to the host web domain. In the latter scenario, the app domain is the domain of the app web.

The main example in this article shows how to build an app that reads data on the app web and displays it in a webpage. The Next steps section shows more scenarios that build on top of the main example.

To follow the examples in this article, you need the following:

  • Visual Studio 2012

  • Office Developer Tools for Visual Studio 2012

  • A SharePoint 2013 development environment (app isolation required for on-premises scenarios)

If you need help setting up a development environment, see Get started developing apps for SharePoint.

In this example, there is a simple page hosted outside of SharePoint that uses a Representational State Transfer (REST) endpoint to read data in a SharePoint website (the app web). Since the cross-domain library requires an app web, it makes sense to start with this scenario.

To read data from the app web, you must do the following:

  1. Create an app for SharePoint and web projects.

  2. Create list items in the app web. This step also ensures that an app web is created when users deploy the app.

  3. Create an app page that uses the cross-domain library to read the list items.

Figure 2 shows a webpage that displays the data on the app web.

Figure 2. Webpage that displays the data on the app web

Cross domain read items sample result screen

Create an app for SharePoint and web projects

  1. Open Visual Studio 2012 as administrator. (To do this, right-click the Visual Studio 2012 icon on the Start menu, and choose Run as administrator.)

  2. Create a new project using the App for SharePoint 2013 template.

    The App for SharePoint 2013 template in Visual Studio 2012 is located under Templates>Visual C#, Office SharePoint>Apps.

  3. Provide the SharePoint website URL that you want to use for debugging.

  4. Select Provider-hosted as the hosting option for your app.

    Note Note

    You can also use the cross-domain library in a SharePoint-hosted app. However, in a SharePoint-hosted app the app page is already in the app web, in which case it wouldn’t need the cross-domain library to read the list items. For a SharePoint-hosted app sample that reads data in the host web, see Use the cross-domain library in a SharePoint-hosted app (REST) or see Access data from the host web later in this article.

Create list items on the app web

  1. Right-click the app for SharePoint project in Solution Explorer. Choose Add>New Item…

  2. Choose Visual C# Items>Office/SharePoint>List. Set the name of your list to Announcements.

  3. Double click Announcements>Elements.xml. Paste the following XML nodes as children of the ListInstance element.

    <Data>
        <Rows>
            <Row>
                <Field Name="Title">Lorem ipsum 1</Field>
                <Field Name="Body">Sed ut perspiciatis, unde omnis iste...</Field>
            </Row>
            <Row>
                <Field Name="Title">Lorem ipsum 2</Field>
                <Field Name="Body">Sed ut perspiciatis, unde omnis iste...</Field>
            </Row>
        </Rows>
    </Data>
    

To add a new page that uses the cross-domain library

  1. Double-click Default.aspx in the web project in Solution Explorer.

  2. Copy the following code and paste it in the Default.aspx file. The code performs the following tasks:

    • Loads the jQuery library from the Microsoft CDN.

    • Provides a placeholder for the result.

    • Extracts the app web URL from the query string.

    • Loads the cross-domain library JavaScript using the getScript function in jQuery.

      The function loads the required resources and then continues to the specified function, ensuring that the cross-domain library is loaded and available to use by the subsequent code.

    • Instantiates the RequestExecutor object. By default, RequestExecutor uses the app web as the context site.

      Note Note

      You can change the context site to other sites different than the app web by using the AppContextSite endpoint (REST) or object (JSOM). To learn more about AppContextSite, see Access data from the host web later in this article.

    • Issues a REST call to the list items endpoint.

    • Handles successful completion, displaying the list items on the webpage.

    • Handles errors, displaying the error message on the webpage.

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="SharePointApp3Web.Pages.Default" %>
    <!DOCTYPE html>
    <html>
        <head>
            <title>Cross-domain sample</title>
        </head>
        <body>
            <!-- This is the placeholder for the announcements -->
            <div id="renderAnnouncements"></div>
            <script 
                type="text/javascript" 
                src="//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.js">
            </script>
            <script type="text/javascript">
              var hostweburl;
              var appweburl;
    
              // Load the required SharePoint libraries
              $(document).ready(function () {
                //Get the URI decoded URLs.
                hostweburl =
                    decodeURIComponent(
                        getQueryStringParameter("SPHostUrl")
                );
                appweburl =
                    decodeURIComponent(
                        getQueryStringParameter("SPAppWebUrl")
                );
    
                // resources are in URLs in the form:
                // web_url/_layouts/15/resource
                var scriptbase = hostweburl + "/_layouts/15/";
    
                // Load the js files and continue to the successHandler
                $.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest);
              });
    
              // Function to prepare and issue the request to get
              //  SharePoint data
              function execCrossDomainRequest() {
                // executor: The RequestExecutor object
                // Initialize the RequestExecutor with the app web URL.
                var executor = new SP.RequestExecutor(appweburl);
    
                // Issue the call against the app web.
                // To get the title using REST we can hit the endpoint:
                //      appweburl/_api/web/lists/getbytitle('listname')/items
                // The response formats the data in the JSON format.
                // The functions successHandler and errorHandler attend the
                //      sucess and error events respectively.
                executor.executeAsync(
                    {
                      url:
                          appweburl +
                          "/_api/web/lists/getbytitle('Announcements')/items",
                      method: "GET",
                      headers: { "Accept": "application/json; odata=verbose" },
                      success: successHandler,
                      error: errorHandler
                    }
                );
              }
    
              // Function to handle the success event.
              // Prints the data to the page.
              function successHandler(data) {
                var jsonObject = JSON.parse(data.body);
                var announcementsHTML = "";
    
                var results = jsonObject.d.results;
                for (var i = 0; i < results.length; i++) {
                  announcementsHTML = announcementsHTML +
                      "<p><h1>" + results[i].Title +
                      "</h1>" + results[i].Body +
                      "</p><hr>";
                }
    
                document.getElementById("renderAnnouncements").innerHTML =
                    announcementsHTML;
              }
    
              // Function to handle the error event.
              // Prints the error message to the page.
              function errorHandler(data, errorCode, errorMessage) {
                document.getElementById("renderAnnouncements").innerText =
                    "Could not complete cross-domain call: " + errorMessage;
              }
    
              // Function to retrieve a query string value.
              // For production purposes you may want to use
              //  a library to handle the query string.
              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];
                }
              }
            </script>
        </body>
    </html>
    

To build and run the solution

  1. Press the F5 key.

    Note Note

    When you press F5, Visual Studio builds the solution, deploys the app, and opens the permissions page for the app.

  2. Choose the Trust It button.

  3. Choose the app icon on the Site Contents page.

If you prefer downloadable code samples, you can get this one from code gallery. Code sample: Get list items by using the cross-domain library using REST or JSOM.

Table 2. Troubleshooting the solution

If you see…

Then try…

Error message: Sorry, we had some trouble accessing your site.

There is also a button to fix the error, but it doesn’t correct the problem.

You may have hit a known problem with security zones in Internet Explorer, see Work with the cross-domain library across different Internet Explorer security zones in apps for SharePoint.

Error message: The required functionalities are not supported by your browser. Please make sure you are using IE 8 or above, or other modern browser. Please make sure the 'X-UA-Compatible' meta tag is set to be 'IE=8' or above.

The cross-domain library requires a document mode of IE8 or above. In some scenarios, the document mode is set to IE7 by default. You can use the Internet Explorer developer tools to determine and change the document mode of your page. For more information, see Defining Document Compatibility.

Error message: 'Type' is undefined.

Additionally, your app uses the JavaScript Object Model (JSOM).

The JSOM uses the Type.registerNamespace method in the Microsoft Ajax library to register the SP namespace. Use the following code to add a reference to the Microsoft Ajax library from your page:

<script 
 type="text/javascript" 
 src="//ajax.aspnetcdn.com/ajax/4.0/1/MicrosoftAjax.js">
</script>

This article shows how to query a REST endpoint to read data from the app web by using an app page that is not hosted on SharePoint. You can also explore the following scenarios and details about the cross-domain library.

Use the JSOM to read data from the app web

Depending on your preference, you might want to use the JSOM instead of REST to query data from the app web. You must complete additional tasks to use the cross-domain library with JSOM:

  • Reference the SharePoint JSOM in your app page.

  • Initialize the ProxyWebRequestExecutorFactory object and set it as the factory of the context object.

  • Access the SharePoint objects to read the data from the list.

  • Load the objects in the context and execute the query.

For a code sample that shows how to perform the tasks, see Get list items by using the cross-domain library (JSOM). For more information on how to use the JSOM, see Using the JavaScript object model (JSOM) in apps for SharePoint.

Access data from the host web

The example in this page shows how to read data from the app web. This works fine as the starting example because the cross-domain library initially uses the app as the context site. However, there are many scenarios where you want to access data on the host web. There are a few tasks required to access data on the host web:

  • Set the host web as the context site for the cross-domain library.

  • Provide appropriate permissions to the app.

You can change the context site by using the AppContextSite endpoint (REST) or object (JSOM). The following example shows how to change the context site using the REST endpoint:

executor.executeAsync(
    {
        url:
            appweburl +
            "/_api/SP.AppContextSite(@target)/web/title?@target='" +
            hostweburl + "'",
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        success: successHandler,
        error: errorHandler
    }
);

The following code example shows how to change the context site using JSOM:

context = new SP.ClientContext(appweburl);
factory = new SP.ProxyWebRequestExecutorFactory(appweburl);
context.set_webRequestExecutorFactory(factory);
appContextSite = new SP.AppContextSite(context, hostweburl);

this.web = appContextSite.get_web();
context.load(this.web);

By default, your app has permissions to the app web, but not to the host web. The following example shows a manifest section that declares a permission request to read data from the host web:

<AppPermissionRequests>
    <AppPermissionRequest 
        Scope="http://sharepoint/content/sitecollection/web" 
        Right="Read" />
</AppPermissionRequests>

Make sure that you create a resource on the app web (like an empty page or list) to force the provisioning of the app web, which is required to use the cross-domain library.

Access data across site collections

With the cross-domain library, you can access data across site collections in the same tenant. There are some tasks that you need to complete to access data across site collections:

  • Add a permission request to access data in the tenant.

  • In your code, switch the context site to the site collections that you want to query.

  • Add the app to the app catalog.

  • Deploy the app as a tenant-scoped app to a website. For an example on how to deploy as a tenant-scoped app, see the description of the Use the cross-domain library in a tenant-scoped app (REST) code sample.

Your app also needs permission to access data from the tenant. The following example shows a manifest section that declares a permission request to read data from the tenant:

<AppPermissionRequests>
  <AppPermissionRequest 
    Scope="http://sharepoint/content/tenant" 
    Right="Read" />
</AppPermissionRequests>

To switch the context site in your code, use the AppContextSite endpoint (REST) or object (JSOM), just like in the Access data from the host web section. Here is a reminder of the REST endpoint: /_api/SP.AppContextSite(@target)/web/title?@target='weburl', and an example on how to instantiate the object in JSOM: appContextSite = new SP.AppContextSite(context, weburl);.

As a developer, you can only deploy tenant-scoped apps from the app catalog. You can provision an app catalog to your on-premises or SharePoint Online environments. Uploading your app to the app catalog is as simple as uploading a file to a document library. See Add custom apps to the App Catalog site for detailed instructions.

From the app catalog you can deploy the app to one or more websites in the tenant. Since your app has permissions to access data in the tenant, you only have to deploy to one website to access data on the whole tenant. See Deploy a custom app for instructions on how to deploy an app from the app catalog.

To download a code sample that shows how to access data across site collections, see Use the cross-domain library in a tenant-scoped app (REST).

Issuing calls across different security zones

The cross-domain library uses a proxy page that is hosted in an IFrame on the app page to enable communication. When the app page and SharePoint website are in different security zones, authorization cookies can’t be sent. If there are no authorization cookies, and the IFrame tries to load the proxy page, it will be redirected to the SharePoint sign-in page. The SharePoint sign-in page can’t be contained in an IFrame for security reasons. In these scenarios, the library cannot load the proxy page, and communication with SharePoint is not possible.

However, there is a solution for these scenarios. The solution is the apphost pattern, which consists in wrapping the app pages in a page hosted in the app web. It’s a good idea to use the apphost pattern in apps that use the cross-domain library, even if there are no evident security boundaries. For more information, see Work with the cross-domain library across different Internet Explorer security zones in apps for SharePoint.

Access data from an additional remote host in a SharePoint-hosted app

By default, a SharePoint-hosted app is allowed to issue cross-domain calls to the host web, provided that it has proper permissions. However, a SharePoint-hosted app can also specify a remote host in the AllowedRemoteHostUrl attribute of its AppPrincipal. This effectively lets you issue cross-domain calls from the app web and from another host elsewhere.

To download a sample of a SharePoint-hosted app that uses the cross-domain library, see Code sample: Use the cross-domain library in a SharePoint-hosted app (REST).

Show:
© 2014 Microsoft