I have two site collections on the same farm (on-prem SP 2016), but different domains (business.* and projects.*). I have full control on both sites. And yet, I cannot access one from the other. I tried ExecutorRequest

var executor = new SP.RequestExecutor(appweburl);

var service = appweburl+ "/_api/SP.AppContextSite(@target)/web/lists/getbytitle('Release')/items?$select=Id,Title,ProjectDeliveryId&$orderby=Title&$top=1000&@target='" + hostweburl + "'";
      url: service, //appweburl + "/Projects/_api/web/lists/getbytitle('Release')/items?$select=Id,Title,ProjectDeliveryId&$orderby=Title&$top=1000&@target='" + hostweburl + "'",
      method: "GET",
                 "Origin": "https://business.test2016.zaba.hr",
                 "Access-Control-Allow-Origin": "https://business.test2016.zaba.hr/ICT/Gate2"
      success: fillReleases,
      error: onQueryFailed

This comes back with 403 FORBIDDEN - The server understood your request, but refuses to fulfill it.

Same with JSOM

var ctx = new SP.ClientContext(appweburl);
        var factory = new SP.ProxyWebRequestExecutorFactory(
        var appContextSite = new SP.AppContextSite(ctx, hostweburl);
        console.log(appweburl, factory, ctx, appContextSite, hostweburl);
        list = appContextSite.get_web().get_lists().getByTitle("Release");
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml("<View><ViewFields><FieldRef Name='ID' /><FieldRef Name='Title' /></ViewFields><QueryOptions><RowLimit>10</RowLimit></QueryOptions></View>");
        var collListItem = list.getItems(camlQuery);
        ctx.load(collListItem, 'Include(Id, Title)');
        ctx.executeQueryAsync(function() { console.log("success", list); fillReleases(); }, function(jqXHR, textStatus, errorThrown) {console.log("fail"); onQueryFailed(jqXHR, textStatus, errorThrown);} );

I tried with and without Origin and Access-Control headers. Both collections have Trust and Allow-Origin set to one another. Detailed logs show that the IFrame is created, but the final message comes as "There is no AppContext in which to execute the request".

I have also tried DataView, page access through javascript request, page viewer and other obvious solutions.

I have full control of the Farm and both Collections so whatever you suggest can be tried. I would like to avoid server side programming - I know I can make HTTP handler, web service etc...


Basically, the core problem is in the JS Cross-Domain requests. If you also have control over the web server, you can try to edit web.config - allow CORS in SharePoint 2013 web.config, the only thing that with credentials you can set only one trusted URL.

  • Yes, I know. The links you provide are different than those I checked and I will definitely try everything, but as I said in the post above "I tried with and without Origin and Access-Control headers" :) Thank you for detailed links, I'll let you know if it works. – Siniša Hajnal May 7 at 12:31
  • Try to modify one target web.config (on data source collection) according to that article and then try to make usual JS XHR/Fetch request to this data source site collection REST API from your second one. As far as I remember you don't need any special headers if CORS is enabled in web.config. As far as I remember the trick could be with POST requests, there you'll need URL rewrite to accept the first request with 200. Also, I'm not sure if SharePoint JSOM will work with CORS. I worked this way with the REST API. – user2866534 May 8 at 15:02

So, finally I managed to get to the solution. Yes, it was CORS problem. Yes, it needed server adjustments as mentioned earlier. But the critical part adding beforeSend part in Ajax. I'm assuming this is so that origin is set before the first handshake between the domains

beforeSend: function(XMLHttpRequest){
        XMLHttpRequest.setRequestHeader("Accept", "application/json; odata=verbose");

Thanks everyone who tried to resolve this with me, I hope this helps someone with similar problems.

Your Answer

