Oggi vediamo come possiamo richiamare servizi esterni tramite una SharePoint-Hosted App.

Questa tipologia di applicazioni, al contrario delle Provider-Hosted, ha le sue pagine e i suoi file Javascript installati fisicamente all'interno di SharePoint e questi vengono esposti su un dominio differente da quello del sito SharePoint in cui l'App è stata installata.
Inoltre, all'interno di queste App non c'è la possibilità di utilizzare codice server-side, quindi dobbiamo fare tutto via Javascript.
Proprio per questi due motivi, immaginando di implementare un'App che stampi a video gli elementi di un feed RSS (in questo caso il mio), la seguente chiamata AJAX:

//wrong method, because throws a cross-domain exception!        
$.ajax({
    url: 'http://www.peppedotnet.it/syndication.axd',
    type: 'GET',            
    success: function (data) {
        //we can't get the result here
    },
    error: function (jqXHR, textStatus, errorThrown) {
    }
});  

ci ritornerà un errore.
Questo perchè stiamo facendo una chiamata "cross-domain" da Javascript, violando così una delle principali regole di sicurezza definite dal W3C e implementate dai vari browser.

Il team di SharePoint però ha visto bene di trovare un alternativa a questo problema.
Non potevano lasciarci lavorare su un nuovo dominio, senza darci la possibilità di richiamare servizi esterni. Sarebbe stato folle.
La soluzione è quella di utilizzare le classi SP.WebRequestInfo e SP.WebProxy presenti all'interno della libreria sp.js che, in parole povere, effettuano la chiamata alla risorsa esterna al posto nostro passando server-side. Così facendo la chiamata cross-domain viene evitata abilmente.
La classe SP.WebProxy effettua una chiamata al server SharePoint (quindi senza effettuare una chiamata cross-domain), il server SharePoint effettua la chiamata alla risorsa esterna e ritorna il risultato al client.

Ecco quindi il codice che possiamo utilizzare per effettuare la chiamata HTTP ad una risorsa esterna alla nostra App.

var results = [];

var context = SP.ClientContext.get_current();
var request = new SP.WebRequestInfo();
request.set_url('http://www.peppedotnet.it/syndication.axd');
request.set_method('GET');

//SharePoint makes the cross-domain call for you!
var response = SP.WebProxy.invoke(context, request); 
context.executeQueryAsync(function () {
    if (response.get_statusCode() == 200) {
        var rss = response.get_body();
        var items = $(rss).find('item');
        $.each(items, function (index, item) {
            results.push({
                Id: $(item).find('guid').text(),
                Title: $(item).find('title').text(),
                Url: 'http://www.peppedotnet.it' + $(item).find('guid').text(),
                Category: $(item).find('category').text(),
                Body: $(item).find('description').text()
            });
        });
    }
}, function (sender, args) {
     alert('error');
});  

Ok, fatto questo ci manca solo un ultimo passo per completare la nostra App. Dobbiamo specificare all'interno dell'App Manifest l'indirizzo della risorsa esterna che la nostra applicazione utilizza in fase di esecuzione. Così facendo, ci assicuriamo che SharePoint effettui la chiamata HTTP al posto nostro verso la risorsa esterna, al posto di ritornare una SecurityException.



Questo è il modo in cui SharePoint valida le richieste che arrivano dalle varie App.
Ecco quindi la nostra App funzionante.


Vi lascio i sorgenti, così potete vedere per bene il funzionamento dell'applicazione: