Dynamics 365Dynamics 365 Le blog vedette de cette semaine vient de notre directeur de la technologie, Daoi Arnason, basé au siège social d’AGR Dynamics en Islande. Il explique comment l’équipe de développement a travaillé pour intégrer AGR 5 avec Microsoft Dynamics 365. Comme toujours, si vous avez des questions ou des commentaires concernant ce blog, n’hésitez pas à commenter ci-dessous, tweetez @AGRDynamics, ou contactez-nous ici.

 

Avec la dernière version de son ERP phare (anciennement connu sous le nom d’AX, mais désormais rebaptisé Dynamics 365 for Operations, dans cet article je l’appellerai AX365), Microsoft a décidé son déploiement à court terme exclusivement vers le cloud, et donc éliminer l’option de déploiement sur site pour ses clients.

Ceci fournit aux fournisseurs de logiciels tiers (comme AGR) de nouveaux défis pour pouvoir s’intégrer aux systèmes AX365. Les solutions AGR ont été intégrées avec succès aux différentes versions d’AX. Ce que ces solutions ont en commun, c’est qu’elles sont effectuées de base à base. Ceci n’est toutefois pas possible lors de l’intégration avec AX365.

Le déploiement d’AX365 étant basé sur un environnement contrôlé par Microsoft (appelé cloud public), AGR doit communiquer avec AX365 via des points de terminaison OData ou des services Web personnalisés AX. La solution à ce problème peut être décomposée en 2 phases.

 

AX365 Développement

Microsoft a introduit le concept du Common Data Model qui vise à être une plate-forme d’intégration entre leurs différentes solutions cloud telles que AX365, CRM et BI. Les entités de données dans AX365 font partie de cette plate-forme. Avec les entités de données vient la possibilité d’exposer des points de terminaison via webservice en utilisant le protocole OData. Les points de terminaison peuvent renvoyer des données via les formats JSON ou XML. Le projet devient ensuite localisé où les données pertinentes peuvent être consultées dans le modèle de données commun.

L’utilisation du protocole OData nécessite que les fournisseurs tiers se connectent à l’instance AX via l’authentification Service-to-Service via Azure Active Directory (AAD) et AX 365:

  1. Les étapes du DAA sont décrites dans le lien suivant. Une fois que vous avez terminé cette étape dans AAD, vous aurez généré un identifiant client et un secret client, ces valeurs devront être stockées pour une utilisation ultérieure.
  2. Pour configurer AX365 afin de pouvoir authentifier les demandes, un administrateur système doit aller dans le système AX et taper «Applications Azure Active Directory» dans la fenêtre de recherche. Dans l’écran suivant, vous créez une nouvelle application Azure Active Directory en en ajoutant une nouvelle, les champs obligatoires sont les suivants:
    1. ID client: ID client généré via AAD à l’étape précédente.
    2. Nom: le nom de l’application
    3. Identifiant utilisateur: l’utilisateur dans lequel l’application distante va emprunter l’identité une fois connecté.

 

Implémentation du connecteur distant.

Pour extraire des données du système AX365 via OData, la première étape consiste à obtenir un jeton d’authentification auprès d’AAD, le code suivant montre comment cela peut être fait en utilisant la bibliothèque d’authentification Active Directory de Microsoft.

public static string GetAdalToken()
{
    string axOAuthTokenUrl = ConfigurationManager.AppSettings["ax_oauth_token_url"];
    string axClientKey = ConfigurationManager.AppSettings["ax_client_key"];
    string axClientSecret = ConfigurationManager.AppSettings["ax_client_secret"];
    string axBaseUrl = ConfigurationManager.AppSettings["ax_base_url"]; 

    UriBuilder uri = new UriBuilder(axOAuthTokenUrl);
 
    AuthenticationContext authenticationContext = new AuthenticationContext(uri.ToString());
    ClientCredential credentials = new ClientCredential(axClientKey, axClientSecret);
 
    AuthenticationResult authResult = authenticationContext	.AcquireTokenAsync(axBaseUrl, credentials).Result;
 
    return authResult.CreateAuthorizationHeader();
}

Les constantes suivantes doivent être stockées dans un fichier de configuration:

  • Axe OAuth Token URL: L’URL utilisée pour obtenir le jeton d’authentification d’AAD, le format habituel est https://login.windows.net/<azure_tenant>/oauth2/token)
  • ID client AX: ID client généré dans DAA
  • AX Client Secret: Le secret client généré dans DAA
  • AX Base Url: L’URL de base de l’implémentation AX

L’étape suivante consiste ensuite à générer des classes proxy pour chaque entité de données. AGR utilise un addon dans Visual Studio pour y parvenir (Générateur de code client OData v4, https://github.com/odata/odata.net). Les proxys sont générés en fonction des métadonnées qui peuvent être trouvées sur le noeud final: http: // <ax_base_url> / data. On peut utiliser les métadonnées téléchargées pour trouver le nom du point de terminaison pour chaque entité de données.

AGR lit les données via une méthode personnalisée qui permet de réutiliser l’appel Web pour tous les points de terminaison, voir ci-dessous:

 

private static async Task<GenericJsonOdata<T>> CallOdataEndpoint<T>(string requestUri)
{            
    var request =(HttpWebRequest)HttpWebRequest.Create(requestUri);
    request.Accept = "application/json;odata.metadata=none";
    string token = Authenticator.GetAdalToken();
    request.Headers["Authorization"] = token;
    request.Method = "GET";
    var result = new GenericJsonOdata<T>();
    try
    {
        using (var response = (HttpWebResponse)request.GetResponse())
        {
            using (var responseStream = response.GetResponseStream())
            {
                using (var streamReader = new StreamReader(responseStream))
                {
                    var responseString = streamReader.ReadToEnd();
                    result = JsonConvert.DeserializeObject<GenericJsonOdata<T>>(responseString);
                    return result;
                }
            }
        }
    }
    catch(WebException e)
    {
        using (var rStream = e.Response.GetResponseStream())
        {
            using (var reader = new StreamReader(rStream))
            {
                result.Exception = JsonConvert.DeserializeObject<AxBaseException>(reader.ReadToEnd());
                return result;
            }
        }
    }
}

 

GenericJsonObject est une classe nécessaire pour pouvoir convertir les données JSON reçues en une collection de classes d’entités:

 

public class GenericJsonOdata<T>
{
    public GenericJsonOdata()
    {
        value = new List<T>();
    }
    public List<T> value { get; set;}

    [JsonProperty("@odata.nextLink")]
    public string NextLink { get; set; }

    public AxBaseException Exception { get; set; }
}

 

Une chose intéressante dans la classe ci-dessus est la propriété NextLink; OData envoyé depuis AX365 limite le nombre d’entités à 10K. Si la limite a été appliquée, les données JSON incluront la propriété pour @ odata.nextLink appelée, si la propriété existe dans le JSON, elle peut être utilisée pour faire une boucle sur les entités de données du côté AX.

AGR est fier de vous présenter que, grâce à la méthode décrite ci-dessus, nous sommes en mesure d’intégrer notre produit phare AGR 5 à AX365.

 

 

Facebook Comments
Facebooktwitterredditlinkedin