0

I have created a provider hosted app for a SharePoint Online site and want to use JavaScript for most of the front end logic, rather than ASP.NET MVC

I have run into Cross domain problems trying to query REST endpoints from the SharePoint Online domain. this article gives advice on getring a basic example up and running for a JavaScript SharePoint provider hosted app, however it doesn't seem to work for me, as I don't have an SPAppWebUrl paramater in the url...

So I tried just using my app domain as the SPAppWebUrl which is something like https://testapp.azurewebsites.net/ but it doesn't seem to work, giving the error

GET 404 testapp.azurewebsites.net/_api/Web/Lists/getByTitle('Customers')/items/?$select=Id,FirstName,Title (Not Found)

That error makes sense to me, as the test app isn't a SharePoint Online site... If I change it to the SPHostWebUrl, it has the correct endpoint mysite.sharepoint.com/sites/dev/_api/Web/Lists/getByTitle... but won't work because of the cross domain restriction, giving the error:

Uncaught SecurityError: Blocked a frame with origin xxxx accessing a frame with origin xxx. Protocols, domains, and ports must match.

Here is my code for a very simple JavaScript app to get some list data. The Endpoint opens fine in the browser when I set it to the SPHostWebUrl but not in the app due to the cross domain error

$(document).ready(function () {
    $.getScript(
        "Scripts/SP.RequestExecutor.js",
        continueExecution
      );
});

function continueExecution() {
    // have tried both hostweburl and appweburl 
    executor = new SP.RequestExecutor(hostweburl);
    getCustomers();
}    

function getCustomers() {

    // begin work to call across network
    var requestUri = hostweburl + "/_api/Web/Lists/getByTitle('Customers')/items/" 
    + "?$select=Id,FirstName,Title";

    // execute AJAX request 
    executor.executeAsync({
        url: requestUri,
        method: "GET",
        headers: { "ACCEPT": "application/json;odata=verbose" },
        contentType: "application/json",
        success: function (data) {
            console.log(data);
        },
        error: function (data) {
            console.log(data);
        }
    });
}
0

You definitely need an app web, because you need to use SP.RequestExecutor.js to make the cross domain calls using javascript -- this depends on having an app web to perform the cross site communication.

Something else worth noting is that the terminology used sometimes can be confusing on the webs...

  • HostWeb: your main SharePoint portal site, where you install your 'App' in SharePoint
  • AppWeb: a special web created in a separate sub-domain of your SharePoint site with the AppId as part of the URL (https://App_Prefix - App_ID . App_Base_Domain / Domain_Relative_URL_of_Host_Web / App_Name)-- this is where SharePoint hosted apps live and Provider Hosted Apps may or may not have this.
  • RemoteWeb: the location of your Provider hosted App -- for you this is located at testapp.azurewebsites.net according to your post

Once you have an app web, you'll need the AppWeb url passed as a parameter to your provider hosted app, you'll need it in order to create the RequestExecutor.

You can find many articles out there about how to use SP.RequestExecutor, but here is a basic example that makes a call to the host web and fetches the title:

// get your hostWebUrl somewhere above here...
var scriptbase = hostWebUrl + "/_layouts/15/";

$.getScript(scriptbase + "SP.RequestExecutor.js", execCrossDomainRequest);

function execCrossDomainRequest() {
    // a boilerplate helper to get a QueryString parameter, you'll have to figure this part out...
    var appWeburl = getQueryStringParameter("SPAppWebUrl"); 
    var executor = new SP.RequestExecutor(appWebUrl);

    executor.executeAsync(
        {
            url: appWebUrl +
                "/_api/Sp.AppContextSite(@target)/web/title?@target='" +
                hostWebUrl + "'",
            method: "GET",
            headers: { "Accept": "application/json;odata=verbose" },
            success: function(data) { console.log(data) },
            error: function(sender, args) { console.log(args) }
        }
    );
}

Not the best success and error handlers, but you get the idea... Note that the executor is targeting the appWebUrl and then switching to the host web context with the SP.AppContextSite endpoint

Adding the site column to your project shouldn't have changed your hosting type, it should have just scaffolded out a bunch of things you need to have inside of your app web -- if you still have two projects inside of your solution you should be fine -- it's just that each project needs to be deployed to their respective location (the AppWeb to SharePoint, and your provider ASP.NET app to Azure).

See another answer I've provided to a similar question here on SharePoint SE for more info, although it deals with JSOM instead of REST.

If you want a MUCH more comprehensive answer than you'll get on here, check out a couple of modules in an Microsoft Virtual Academy series by Scott Hillier and Ted Pattison at http://www.microsoftvirtualacademy.com/training-courses/deep-dive-into-the-office-365-app-model

You'll be particularly interested in Module 6, 28:00 (Programming in Javascript), but I strongly recommend all of modules 5, 6, and 7.

And you would probably also find the intro series helpful, you can find it here: http://www.microsoftvirtualacademy.com/training-courses/introduction-to-office-365-development modules 3, 4, 7, and 8 are probably the most applicable in that series.

Watch the videos!

  • Thanks for your feedback, I have a bit more knowledge now on the 2 different projects in the solution, and how one is the SharePoint app, deployed to the site, and the other the web site publishing to Azure. I was a bit confused on that. I will watch the videos tonight and see if they can help me out. – svnm Dec 8 '14 at 1:54
  • My main problem now is, I set up my app, with a Client Secret and id. It works no problem, but then I make the required change to the AppManifest.xml file <Internal AllowedRemoteHostUrl="testapp1.azurewebsites.net/"> then it falls over giving the following error An unexpected error has occurred. Please try again by launching the app installed on your site – svnm Dec 8 '14 at 1:55
  • You shouldn't need to set the AllowedRemoteHostUrl property to access data in the app web or host web from your remote web. Scott Hillier has his code/projects from that video I posted up on github at github.com/OfficeDev/TrainingContent/tree/master/…, there's nothing there about RemoteHostUrl inside the <AppPrincipal> node – John-M Dec 8 '14 at 2:44
2

I came across this scenario a little while back. If i'm not mistaken, I think you will need to 'create' an App Web as a proxy for your REST calls.

You also need to alter the AppManifest.xml to add the following entry: <Internal AllowedRemoteHostUrl="~remoteAppUrl"/> in place of <RemoteWebApplication ClientId="*" />

However, this will also prevent you from using CSOM in code behind if you wish to do so.

I followed the steps here from Steve Peschka in order to get this to work.

  • No that didn't work for me, adding a Site Column as he suggests, then updating the AppManifest.xml changes the hosting type for the app to a SharePoint hosted app for me, adding in a feature and package... Oh well, seems very difficult to try to use JavaScript REST approach for a provider hosted app – svnm Dec 2 '14 at 23:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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