Tramite uno script è possibile importare dati da Microsoft Dynamics 365 utilizzando il protocollo oData e autenticandosi tramite il protocollo oAuth2.
Queste tecnologie rappresentano lo stato dell’arte per quanto riguarda rispettivamente l’accesso ai dati RESTful e l’autenticazione a servizi in Cloud, e l’esempio sotto riportato è quindi particolarmente importante costituendo un punto di partenza dal quale derivare altre soluzioni facendo uso di tali tecnologie.
Autenticazione oAuth2
Il protocollo oAuth2 viene utilizzato sia da Microsoft che da Google per l’accesso ai rispettivi servizi Cloud. Nel caso di Microsoft, e quindi di Dynamics 365, la gestione degli utenti avviene tramite Azure Active Directory (AAD), che fra le altre cose è in grado di gestire l’appartenenza degli utenti stessi ad un dominio specifico (quello dell’azienda, es. “qualiware.it”). Pertanto ogni azienda potrà usare il proprio dominio e registrare gli utenti sulle varie applicazioni.
Una applicazione esterna, come ad esempio QualiWare, dovrà effettuare apposite chiamate per autenticarsi e utilizzare i servizi messi a disposizione dall’applicazione Microsoft, e per fare questo non è sufficiente disporre di un utente e una password, ma sarà necessario registrare l’applicazione esterna stessa all’interno di AAD, per ottenere il cosiddetto Application ID (spesso chiamato anche Client ID) che andrà specificato nelle suddette chiamate.
L’autenticazione con utente e password è possibile se l’applicazione esterna è registrata come “Native”. Se viene registrata come “Web App/Api”, è necessario utilizzare il cosiddetto “Client Secret”, che viene reperito nella scheda di registrazione dell’app all’interno di Active Directory.
Le immagini seguenti riportano un esempio di maschera di registrazione “Native” e “Web App/Api” all’interno di AAD.
- Registrazione Web App
- Registrazione Native App
Accesso ai dati tramite protocollo oData
Il protocollo oData è un’implementazione del paradigma REST, e consente di effettuare operazioni di interrogazione e aggiornamento utilizzando il protocollo Web.
Componendo opportunamente una URL, è possibile specificare la tabella da interrogare, i filtri e l’operazione da effettuare. Ad, esempio, per reperire i primi 100 records della tabella Customers, si può utilizzare una URL di questo tipo:
https://<dominio applicazione>.sandbox.ax.dynamics.com/data/CustomersV3?$top=100
Il risultato restituito è un file JSon contenente i dati, che può essere facilmente elaborato utilizzando la libreria Newtonsoft.Json già inclusa nella piattaforma QualiWare, come vedremo nell’esempio successivo.
Per ulteriori informazioni:
Esempio di codice
Il seguente codice effettua l’autenticazione a Dynamics 365 utilizzando nome utente e password, e reperisce i primi 1000 clienti visualizzandoli un un oggetto campo testo multiriga.
Dim credential As New Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential("<user>", "<password>") Dim authContext As Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext = New Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.windows.net/<dominio azienda>.com", False) ' Il ClientID (secondo parametro) è l'Application ID registrato su Dynamics ' NOTA: per potere usare utente e password, l'AppID deve essere registrata come "Native". ' Se invece è registrata come Web App/Api, è necessario ricevere “Client Secret” e “ClientID”, e usare queste creare le credenziali Dim res As Threading.Tasks.Task(Of Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult) res = Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions.AcquireTokenAsync(authContext, "https://<dominio applicazione>.sandbox.ax.dynamics.com", "8da6079a-390a-4eb5-9b08-eeda3066cb7b", credential) res.Wait Dim token As String = res.Result.AccessToken Dim url As String = "https://<dominio applicazione>.sandbox.ax.dynamics.com/data/CustomersV3?$top=1000" ' Recupera i primi 1000 clienti Dim request As System.Net.HttpWebRequest Dim response As System.Net.HttpWebResponse = Nothing Dim reader As System.IO.StreamReader request = DirectCast(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest) request.Headers.Add("Authorization", "Bearer " + token) ' Usa il token recuperato sopra per l'autenticazione response = DirectCast(request.GetResponse(), System.Net.HttpWebResponse) reader = New System.IO.StreamReader(response.GetResponseStream()) Dim json As String json = reader.ReadToEnd() Dim obj As Newtonsoft.Json.linq.JObject=Newtonsoft.Json.linq.JObject.Parse(json) Dim i As integer form.findcontrol("Editor1").Text="" For i=0 To CType(obj("value"), Newtonsoft.Json.Linq.JArray).Count-1 form.findcontrol("Editor1").text+="Codice: "+ctype(obj("value")(i)("CustomerAccount"),Newtonsoft.Json.Linq.JValue).Value+vbcr form.findcontrol("Editor1").text+="Ragione sociale: "+ctype(obj("value")(i)("OrganizationName"),Newtonsoft.Json.Linq.JValue).Value+vbcr form.findcontrol("Editor1").text+="E-mail:"+Ctype(obj("value")(i)("PrimaryContactEmail"),Newtonsoft.Json.Linq.JValue).Value+vbcr form.findcontrol("Editor1").text+="Indirizzo: "+Ctype(obj("value")(i)("FullPrimaryAddress"),Newtonsoft.Json.Linq.JValue).Value+vbcr form.findcontrol("Editor1").text+="Città: "+obj("value")(i)("DeliveryAddressCity").ToString+vbcr form.findcontrol("Editor1").text+="Via: "+ctype(obj("value")(i)("DeliveryAddressStreet"),Newtonsoft.Json.Linq.JValue).Value+vbcr form.findcontrol("Editor1").text+="Provincia:"+ctype(obj("value")(i)("AddressCounty"),Newtonsoft.Json.Linq.JValue).Value+vbcr+vbcr Next
Come si può notare, le parti di autenticazione e interrogazione sono costituite da pochissime righe, e, all’atto pratico, risultano molto efficienti. La parte più complessa è l’elaborazione del risultato, che risulta estremamente semplificato dalla libreria Newtonsoft.Json la quale consente di accedere all’array dei records (contenuto in obj(“value”)) e di estrarne i vari campi, che sono rappresentate da proprietà degli oggetti contenuti nei vari elementi dell’array.