Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I have a web page hosted on a server, say at http://SVR1/path/index.html, and I would like to access some list items in a on-premises SharePoint site hosted on another server, say at http://SVR2/sites/mySite/.

The current installation of SharePoint I am using (not under my control) does not allow deployment of neither SharePoint-hosted nor Provider-hosted apps, so I am trying to use the SharePoint Cross-Domain library to access the desired list items from a purely external HTML5/JS/CSS3 page. I, as a user, have full access rights to the list in my SharePoint site, so I guess it should be no problem reading its items.

Following an example found here, my page is as follows:

<!doctype html>
<html>
<head>
  <!-- Title -->
  <title>Application Template</title>
  <script language="javascript" type="text/javascript" src="js/jquery.js"></script>
  <script language="javascript" type="text/javascript">

    var hostweburl = "http://SVR2/sites/mySite";
    var appweburl  = "http://SVR1/path";

    // Load the required SharePoint libraries
    $(document).ready(function () {

      $("#renderList").html("Requesting Lists...");

      // 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 host web.
      // To get the title using REST we can hit the endpoint:
      //      hostweburl/_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: hostweburl + "/_api/web/lists",
            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 listsHTML = "";

      var results = jsonObject.d.results;
      for (var i = 0; i < results.length; i++) {
        listsHTML = listsHTML +
            "<p><h1>" + results[i].Title +
            "</h1>" + results[i].Body +
            "</p><hr>";
      }

      document.getElementById("renderList").innerHTML =
          listsHTML;
    }

    ///////////////////////////////////////////////////////
    // Function to handle the error event.
    // Prints the error message to the page.
    function errorHandler(data, errorCode, errorMessage) {
      document.getElementById("renderList").innerText =
          "Could not complete cross-domain call: " + errorMessage;
    }
  </script>

</head>

<body>
  <h1 id="Root Page" style="text-align:center;">This is the home page</h1>
  <div id="renderList">Placeholder</div>
</body>
</html>

When I load the page in a browser, in the javascript console I get an error: "Uncaught Error: Invalid field or parameter requestInfo.url.".

I am under the impression that the problem is in the content of variable appweburl that, in all the examples I have found, is provided by SharePoint as part of the query part in the URL. But this implies that a provider-hosted app has been deployed in SharePoint - something I cannot do - and that this app is calling its remotely hosted counterpart.

So the question is: Is it possible to use SharePoint cross-domain library in a page totally external to SharePoint, and if yes, how should I set hostweburl, appweburl and maybe other things to have access to SharePoint lists?

Thanks in advance.

share|improve this question
1  
Have you tried querying the REST api directly? That would bypass the whole app issue. You would be able to get information through SVR/_api/web/lists/GetByTitle('Your_list_name') for example. Some further examples: Link –  Alexander Jun 26 at 11:10
    
Thank you for the link, I'll read it in depth. Concerning the REST API, I have considered it and made some experiments. I successfully accessed the list content but only writing the URL in the browser address bar, while I got a 401-UNAUTHORIZED doing the same thing from JavaScript using XmlHttpRRequest. I think that in the first case the browser provides user authentication and there is no Same Origin Policy problem (a whole new page is loaded), while in the second case I must cope with both an authentication problem and a Same Origin Policy problem, that's why I tried SP Cross-Domain Library –  eca Jun 27 at 7:38
add comment

1 Answer 1

Is it possible to use SharePoint cross-domain library in a page totally external to SharePoint

No, the Cross-domain library for apps for SharePoint is part of SharePoint, it is not available outside of SharePoint.

Here is an example of someone else who had the same requirements.

http://pholpar.wordpress.com/2013/05/11/accessing-office-365-sharepoint-sites-using-rest-from-a-local-html-javascript-host/

For reference, I have pasted their code here:

<script type="text/ecmascript" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>

<script language="ecmascript" type="text/ecmascript">
    var tokenReq = '<?xml version="1.0" encoding="utf-8"?>';
    tokenReq += '<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">';
    tokenReq += '  <soap:Body>';
    tokenReq += '    <GetUpdatedFormDigestInformation xmlns="http://schemas.microsoft.com/sharepoint/soap/" />';
    tokenReq += '  </soap:Body>';
    tokenReq += '</soap:Envelope>';
    // you should set these values according your actual request
    var usr = 'username@yourdomain.onmicrosoft.com';
    var pwd = 'password';
    var siteFullUrl = "https://yourdomain-my.sharepoint.com";
    var loginUrl = siteFullUrl + "/_forms/default.aspx?wa=wsignin1.0";
    var authReq = '<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">';
    authReq += '  <s:Header>';
    authReq += '    <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>';
    authReq += '    <a:ReplyTo>';
    authReq += '      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>';
    authReq += '    </a:ReplyTo>';
    authReq += '    <a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To>';
    authReq += '    <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">';
    authReq += '      <o:UsernameToken>';
    authReq += '        <o:Username>' + usr + '</o:Username>';
    authReq += '        <o:Password>' + pwd + '</o:Password>';
    authReq += '      </o:UsernameToken>';
    authReq += '    </o:Security>';
    authReq += '  </s:Header>';
    authReq += '  <s:Body>';
    authReq += '    <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust"><wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">';
    authReq += '      <a:EndpointReference>';
    authReq += '        <a:Address>' + loginUrl + '</a:Address>';
    authReq += '      </a:EndpointReference>';
    authReq += '      </wsp:AppliesTo>';
    authReq += '      <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>';
    authReq += '      <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>';
    authReq += '      <t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>';
    authReq += '    </t:RequestSecurityToken>';
    authReq += '  </s:Body>';
    authReq += '</s:Envelope>';

    function startScript() {
        getToken();
    }
    var token;
    // Step 1: we get the token from the STS
    function getToken() {
            $.support.cors = true; // enable cross-domain query
            $.ajax({
                type: 'POST',
                data: authReq,
                crossDomain: true, // had no effect, see support.cors above
                contentType: 'application/soap+xml; charset=utf-8',
                url: 'https://login.microsoftonline.com/extSTS.srf',
                dataType: 'xml',
                success: function (data, textStatus, result) {
                    // extract the token from the response data
                    // var token = $(result.responseXML).find("wsse\\:BinarySecurityToken").text(); // we should work with responseText, because responseXML is undefined, due to Content-Type: application/soap+xml; charset=utf-8
                    token = $(result.responseText).find("wsse\\:BinarySecurityToken").text();
                    getFedAuthCookies();
                },
                error: function (result, textStatus, errorThrown) {
                    reportError(result, textStatus, errorThrown);
                }
            });
        }
        // Step 2: "login" using the token provided by STS in step 1

    function getFedAuthCookies() {
        $.support.cors = true; // enable cross-domain query
        $.ajax({
            type: 'POST',
            data: token,
            crossDomain: true, // had no effect, see support.cors above
            contentType: 'application/x-www-form-urlencoded',
            url: loginUrl,
            // dataType: 'html', // default is OK: Intelligent Guess (xml, json, script, or html)
            success: function (data, textStatus, result) {
                // we should update the digest
                //refreshDigestViaWS(); // or alternatively:
                refreshDigestViaREST();
            },
            error: function (result, textStatus, errorThrown) {
                reportError(result, textStatus, errorThrown);
            }
        });
    }
    var digest;
    // Step 3a: get the digest from the Sites web service and refresh the one stored locally
    function refreshDigestViaWS() {
            $.support.cors = true; // enable cross-domain query
            $.ajax({
                type: 'POST',
                data: tokenReq,
                crossDomain: true, // had no effect, see support.cors above
                contentType: 'text/xml; charset="utf-8"',
                url: siteFullUrl + '/_vti_bin/sites.asmx',
                headers: {
                    'SOAPAction': 'http://schemas.microsoft.com/sharepoint/soap/GetUpdatedFormDigestInformation',
                    'X-RequestForceAuthentication': 'true'
                },
                dataType: 'xml',
                success: function (data, textStatus, result) {
                    digest = $(result.responseXML).find("DigestValue").text();
                    sendRESTReq();
                },
                error: function (result, textStatus, errorThrown) {
                    var response = JSON.parse(result.responseText);
                    if ((response.error != undefined) && (response.error.message != undefined)) {
                        alert(response.error.message.value);
                    }
                }
            });
        }
        // Step 3b: get the digest from the contextinfo and refresh the one stored locally

    function refreshDigestViaREST() {
            $.support.cors = true; // enable cross-domain query
            $.ajax({
                type: 'POST',
                data: tokenReq,
                crossDomain: true, // had no effect, see support.cors above
                contentType: 'text/xml; charset="utf-8"',
                url: siteFullUrl + '/_api/contextinfo',
                dataType: 'xml',
                success: function (data, textStatus, result) {
                    digest = $(result.responseText).find("d\\:FormDigestValue").text();
                    sendRESTReq();
                },
                error: function (result, textStatus, errorThrown) {
                    var response = JSON.parse(result.responseText);
                    if ((response.error != undefined) && (response.error.message != undefined)) {
                        alert(response.error.message.value);
                    }
                }
            });
        }
        // Step 4: send the REST request

    function sendRESTReq() {
        $.support.cors = true; // enable cross-domain query
        $.ajax({
            type: 'POST',
            data: JSON.stringify({
                __metadata: {
                    type: 'SP.List'
                },
                Title: 'RESTDocLib',
                BaseTemplate: 101
            }),
            // equivalent:       
            // data: "{'__metadata': { 'type': 'SP.List' }, 'Title': 'RESTDocLib','BaseTemplate': 101}" ,
            url: siteFullUrl + "/_api/web/lists",
            crossDomain: true, // had no effect, see support.cors above
            contentType: 'application/json;odata=verbose',
            headers: {
                'X-RequestDigest': digest,
                "Accept": "application/json; odata=verbose"
            },
            success: function (data, textStatus, result) {
                alert("Created");
            },
            error: function (result, textStatus, errorThrown) {
                var response = JSON.parse(result.responseText);
                if ((response.error != undefined) && (response.error.message != undefined)) {
                    alert(response.error.message.value);
                }
            }
        });
    }

    function reportError(result, textStatus, errorThrown) {
        var response = JSON.parse(result.responseText);
        if ((response.error != undefined) && (response.error.message != undefined)) {
            alert(response.error.message.value);
        }
    }
    $(document).ready(startScript);
</script>
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.