Durante questi periodi stiamo imparando a conoscere la nuova interfaccia REST di SharePoint 2013. Questa interfaccia è una figata perchè permette di sfruttare gli standard del momento, in ambito di sviluppo web, per la scrittura delle vostre applicazioni.
Applicazioni che vedono un utilizzo molto più accentuato di JavaScript, rispetto a quanto si aveva prima.
Perchè JavaScript? Perchè lo impone il mercato attuale. Applicazioni con una forte user experience ed un utilizzo di tecnologie client-side ben distribuito sono sicuramente di impatto per l'utente finale e pensare di poter affiancare a queste tecnologie una base server-side orientata ai servizi, molto solida e basata su standard come JSON, ecc.. è sicuramente rassicurante.
Benissimo. Il problema è che in questo momento storico, soprattutto qui in Italia, noi "SharePointiani" è come se fossimo sotto attacco. Si perchè dobbiamo avere a che fare con molti clienti che usano ancora MOSS 2007, la maggior parte che sono ben consolidati su SharePoint 2010 e qualche avventuriero che sta iniziando ad utilizzare 2013, il che ci mette in forte difficoltà durante lo sviluppo delle nostre applicazioni. Questo perchè non tutte le tecnologie e le librerie che possiamo sfruttare in questi periodi sono compatibili con software di "vecchia generazione".
Ecco quindi che, se dobbiamo pensare ad un'applicazione su SharePoint 2010 (su MOSS 2007 ci ho messo una pietra sopra ormai), per prima cosa è molto importante che la pensiamo in ottica di una futura migrazione.
Poi, è altrettanto importante che cerchiamo di svilupparla seguendo lo standard del momento, lo standard che si aspettano gli utenti ora, cioè quello di applicazioni molto responsive, di facile utilizzo, che guidano l'utente all'obbiettivo e con un certo appeal grafico e funzionale.
In parole povere, è necessario pensare l'applicazione con una buona dose di sviluppo di front-end ed una solida architettura a servizi.
Se vi ricordate, SharePoint ha sempre esposto molte delle sue funzionalità tramite servizi, ma l'utilizzo di tecnologie attuali come REST per le richieste e JSON per la rappresentazione del dato è stato applicato solamente per un singolo servizio (il ListData.svc), che però ci dava solo la possibilità di fare operazioni sulle liste. Carino eh, però limitante.
Vediamo invece come possiamo scrivere dei servizi personalizzati, in grado di rispondere a chiamate REST e di ritornare i dati nel formato che si ormai presentato come uno dei più vincenti: JSON.

Per prima cosa è necessario aprire Visual Studio 2010 e creare un nuovo progetto SharePoint 2010.
Fatto questo, aggiungete alla vostra soluzione una nuova "mapped folder" e selezionate la cartella "ISAPI", che sarà la cartella che conterrà i nostri servizi.

Creare servizi REST su SharePoint 2010

Perchè la cartella ISAPI? Perchè è la cartella che SharePoint stesso utilizza per i suoi web services e perchè contiene la configurazione (tramite un web.config specifico) per implementare nuovi servizi SOAP o REST.
Fatto questo, dobbiamo aggiungere la referenza alla libreria Microsoft.SharePoint.Client.ServerRuntime.dll; questa libreria si trova solo in GAC (una volta che avete installato SharePoint ovviamente) e contiene le strutture utili alla creazione del nostro servizio custom.

Creare servizi REST su SharePoint 2010

Queste libreria le inseriamo solamente perchè ci danno la possibilità di decorare un nostro servizio con un attributo che fa capire a SharePoint di generare anche l'endpoint "MEX" utile allo scambio dei metadati del servizio.
Oltre a tale libreria dobbiamo aggiungere le varie referenze per l'utilizzo di servizi WCF (quindi per esempio la System.ServiceModel, la System.ServiceModel.Web e la System.Runtime.Serialization).

Creare servizi REST su SharePoint 2010

Benissimo. Passiamo ora alla creazione del servizio.
Ogni servizio WCF deve vedere la presenza di un endpoint (che può essere una URI dinamica o un file .svc) e di un contratto utile a definire quali sono i metodi esposti dal servizio stesso. Per chi di voi già lavora con WCF, queste nozioni dovrebbero essere superflue.
All'interno di una soluzione SharePoint 2010, l'endpoint del nostro servizio personalizzato sarà un file .svc che dovrete create all'interno della cartella "ISAPI". Questo file deve contenere la seguente dichiarazione:

<%@ ServiceHost Language="C#" 

Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory,
Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"

Service="D4S.SP2010.RestService.Services.SampleRESTService,
D4S.SP2010.RestService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=05336b2be73eec53"
%
>


I punti importanti della dichiarazione del servizio appena vista sono:
  • L'attributo "Service", che rappresenta la classe concreta del nostro servizio
  • L'attributo "Factory", che rappresenta la classe factory presente all'interno delle librerie del Server Object Model di SharePoint 2010 e che stabilisce quale tipo di binding SharePoint dovrà applicare al nostro servizio. Nel nostro caso, viene scelta la classe MultipleBaseAddressWebServiceHostFactory che è la classe che ci permette di creare il servizio in modalità REST, al posto di utilizzare SOAP o di creare un servizio ADO.NET Data Service.

Riguardo il secondo punto, vi ricordo che i servizi WCF cambiano comportamento (e talvolta anche protocollo) in base alla configurazione (binding) presente all'interno del web.config dell'applicazione web che funge da host per il servizio.
SharePoint offre un pò di factory di default, in grado di permetterci di creare dei servizi in maniera dinamica (quindi senza darne una vera e propria definizione all'interno del web.config), che sono disponibili a questo indirizzo:
http://msdn.microsoft.com/en-us/library/ff521586(v=office.14).aspx

Creato l'endpoint, dobbiamo specificare il contratto del nostro servizio. Il contratto è solitamente dato dall'utilizzo di un'interfaccia (anche se non è obbligatorio ovviamente), a cui assegnare l'attributo "ServiceContract" e di una serie di metodi, che saranno poi quelli esposti dal servizio, decorati invece con l’attributo "OperationContract".

namespace D4S.SP2010.RestService.Services

{
[ServiceContract]
public interface ISampleRESTService
{
[WebGet(UriTemplate="list", BodyStyle=WebMessageBodyStyle.Bare, ResponseFormat=WebMessageFormat.Json)]
[OperationContract]
List<SampleDto> ReturnAListOfSomething();

[OperationContract]
[WebGet(UriTemplate="list/?id={id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
SampleDto GetSomethingById(int id);

[OperationContract]
[WebGet(UriTemplate = "list/{id}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
SampleDto GetSomethingElseById(string id);
}
}

Come avete visto, su ogni metodo esposto abbiamo la possibilità di specificare:
  • Il template della URL utilizzata per chiamare tale metodo (tramite l'attributo UriTemplate)
  • Il tipo di messaggio
  • Il formato della risposta (assieme a quella della richiesta, che in questo esempio ho omesso)

A tale interfaccia dobbiamo poi legare un'implementazione concreta. La classe che conterrà tale implementazione sarà la stessa che abbiamo definito all'interno dell'endpoint.

namespace D4S.SP2010.RestService.Services

{
[BasicHttpBindingServiceMetadataExchangeEndpoint]
[AspNetCompatibilityRequirements(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
public class SampleRESTService : ISampleRESTService
{
public List<SampleDto> ReturnAListOfSomething()
{
return SampleData();
}

public SampleDto GetSomethingById(int id)
{
return SampleData().Where(s => s.SampleIntProperty == id).FirstOrDefault();
}

public SampleDto GetSomethingElseById(string id)
{
int requestedId = 0;
if (Int32.TryParse(id, out requestedId))
return SampleData().Where(s => s.SampleIntProperty == requestedId).FirstOrDefault();
else
return null;
}

private List<SampleDto> SampleData()
{
return new List<SampleDto>()
{
new SampleDto() { SampleIntProperty = 0, SampleStringProperty = "zero" },
new SampleDto() { SampleIntProperty = 1, SampleStringProperty = "uno" },
new SampleDto() { SampleIntProperty = 2, SampleStringProperty = "due" },
new SampleDto() { SampleIntProperty = 3, SampleStringProperty = "tre" },
};
}
}
}

Ovviamente l'implementazione è solo d'esempio. Quello a cui dovete far caso è l'utilizzo dell'attributo BasicHttpBindingServiceMetadataExchangeEndpoint, per permettere la creazione dinamica dell'endpoint /mex utile allo scambio dei metadati del nostro servizio.

Ok, ci siamo quasi.
Come avete visto, i metodi esposti dal nostro servizio ritornano sia dei tipi di dati base (void, string, int, ecc..) sia dei tipi di dati custom (nell'esempio, il tipo "SampleDto"). Quello che dovete ricordarvi di fare, che chi di voi usa WCF sa bene, è di decorare la classe e le proprietà che abbiamo intenzione di utilizzare all'interno del nostro servizio con gli attributi "DataContract" e "DataMember".
Questi due attributi fanno in modo che il framework di WCF riesca a serializzare i dati che escono dal nostro servizio (nel nostro caso in JSON) e deserializzare quelli che arrivano in entrata.

namespace D4S.SP2010.RestService.Dto

{
[DataContract]
public class SampleDto
{
[DataMember]
public string SampleStringProperty { get; set; }

[DataMember]
public int SampleIntProperty { get; set; }
}
}

Benissimo. Ora possiamo fare deploy della nostra soluzione su SharePoint 2010.
Per testarla ci basta semplicemente aprire il browser, andare all’indirizzo:

http://vostrositosharepoint/_vti_bin/D4S/SampleRESTService.svc

Creare servizi REST su SharePoint 2010

e chiamare uno dei metodi esposti:

http://vostrositosharepoint/_vti_bin/D4S/SampleRESTService.svc/list

Creare servizi REST su SharePoint 2010

http://vostrositosharepoint/_vti_bin/D4S/SampleRESTService.svc/list/2

Creare servizi REST su SharePoint 2010

Ecco pronto il vostro servizio REST, che vi torna dati in formato JSON da utilizzare all’interno della parte di front-end delle vostre applicazioni.
Vi lascio qua i sorgenti, così potete provarlo direttamente:
- D4S.SP2010.RestService.zip (50 Kb)