Press ESC to close

Consuming OData data entities of D365F&O using OData connected service in .Net Framework Console Application

Prerequisite:  

First off, all you need to register an App on      portal.azure.com  

 

Steps 1: Create a .Net Framework Library project.  

 

2024-07-12_3-41-33.jpg

 
2024-07-12_3-44-18.jpg

 

Step 2: Now, go to Extensions and then manage Extensions. Install OData-connected service.  


 

2024-07-12_3-46-11.jpg

 


 

 

1.jpg

 

 

Note: For installation, you need to close your visual studio once. The VSIX installer wizard opens for installation.  

Step 3: We need to add a connected service to the UilityOData library project.     

 

Follow the steps as shown to configure it.  


 

 

2.jpg

 
3.jpg

 

In the address bar, paste the link of your finance and operations cloud-hosted environment URI which you inserted in the Azure portal while registering the app in step 1.  Also, add “/data” at the end of your address to point to the Odata data entities of Dynamics 365 F&O  

 

Click Next and a list of data entities will be shown to you. It will take time depending on the number of data entities. You can select any data entities from the list. For demo purposes, I selected “CustomerGroups” only.  

 

5.jpg

 
Click Next, and then finish. It will also take some time.  

After successful configuration, the OData documentation opens in your any web browser.    
The connected service will include the following files. Build the UtilityOData project and you can see a dll file is also created on a successful build as it is a library project.  


 

 

 

Step 4: Go to Manage Nuget Package to install the following libraries.    
 

1. Microsoft.IdentityModel.Clients.ActiveDirectory    
2. Microsoft.OData.Client (It will be installed with the configuration of the OData connected service so no need to install it separately)  

 

For installation of the Nuget package, right-click on the project and you will see “Manage Nuget Packages”  

Step 5: Create another .Net Framework Library Project.  

 

Create the project in the same solution for simplicity. I name the project as “AuthenticationUtility” as it is a utility for the Authentication of Azure App.  

 

Now, create a class by the name of “ClientConfiguration”. Replace the necessary credentials with yours.  

The ClientConfiguration class is necessary for managing and centralizing the configuration settings required to connect and authenticate.  

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace AuthenticationUtility

{

    public partial class ClientConfiguration

    {

        public static ClientConfiguration Default { get { return ClientConfiguration.OneBox; } }

 

        public static ClientConfiguration OneBox = new ClientConfiguration()

        {

            // You only need to populate this section if you are logging on via a native app. For Service to Service scenarios in which you e.g. use a service principal you don't need that.

           UriString = " environment Url",

            //UserName = "<YourUserName>",

            //Password = "<YourPassword>",

 

            ActiveDirectoryResource = " environment Url ",

            ActiveDirectoryTenant = "https://login.microsoftonline.com/Tenat_ID ", // You can find your tenat from Azure portal

            ActiveDirectoryClientAppId = "Client ID from Azure",

            // Insert here the application secret when authenticate with AAD by the application

            ActiveDirectoryClientAppSecret = "Secret ID from Azure",

 

            // Change TLS version of HTTP request from the client here

            // Ex: TLSVersion = "1.2"

            // Leave it empty if want to use the default version

            TLSVersion = "",

        };

 

        public string TLSVersion { get; set; }

        public string UriString { get; set; }

        //public string UserName { get; set; }

        //public string Password { get; set; }

        public string ActiveDirectoryResource { get; set; }

        public String ActiveDirectoryTenant { get; set; }

        public String ActiveDirectoryClientAppId { get; set; }

        public string ActiveDirectoryClientAppSecret { get; set; }

    }

}

Step 6: Create another class by the name of “OAuthHelper” .  

The    OAuthHelper    class is needed to handle OAuth authentication, which is essential for securely accessing resources and services that require user authentication and authorization.

using AuthenticationUtility;

using Microsoft.IdentityModel.Clients.ActiveDirectory;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

//using Microsoft.Identity.Client;

namespace AuthenticaitionUtility

{

    public class OAuthHelper

    {

        public const string OAuthHeader = "Authorization";

 

        /// <summary>

        /// Retrieves an authentication header from the service.

        /// </summary>

        /// <returns>The authentication header for the Web API call.</returns>

        public static string GetAuthenticationHeader(bool useWebAppAuthentication)

        {

            string aadTenant = ClientConfiguration.Default.ActiveDirectoryTenant;

            string aadClientAppId = ClientConfiguration.Default.ActiveDirectoryClientAppId;

            string aadClientAppSecret = ClientConfiguration.Default.ActiveDirectoryClientAppSecret;

            string aadResource = ClientConfiguration.Default.ActiveDirectoryResource;

 

            AuthenticationContext authenticationContext = new AuthenticationContext(aadTenant, false);

            AuthenticationResult authenticationResult = null;

 

            // OAuth through application by application id and application secret.

            if (useWebAppAuthentication)

            {

                if (string.IsNullOrEmpty(aadClientAppSecret))

                {

                    Console.WriteLine("Please fill AAD application secret in ClientConfiguration if you choose authentication by the application.");

                    throw new Exception("Failed OAuth by empty application secret.");

                }

 

                try

                {

 

                    var creadential = new ClientCredential(aadClientAppId, aadClientAppSecret);

                    authenticationResult = authenticationContext.AcquireTokenAsync(aadResource, creadential).Result;

                }

                catch (Exception ex)

                {

                    Console.WriteLine(string.Format("Failed to authenticate with AAD by application with exception {0} and the stack trace {1}", ex.ToString(), ex.StackTrace));

                    throw new Exception("Failed to authenticate with AAD by application.");

                }

            }

            //else

            //{

            //    // OAuth through username and password.

            //    //string username = ClientConfiguration.Default.UserName;

            //    //string password = ClientConfiguration.Default.Password;

 

            ////    if (string.IsNullOrEmpty(password))

            ////    {

            ////        Console.WriteLine("Please fill user password in ClientConfiguration if you choose authentication by the credential.");

            ////        throw new Exception("Failed OAuth by empty password.");

            ////    }

 

            ////    try

            ////    {

            ////        // Get token object

            ////        var userCredential = new UserPasswordCredential(username, password);

            ////        authenticationResult = authenticationContext.AcquireTokenAsync(aadResource, aadClientAppId, userCredential).Result;

            ////    }

            ////    catch (Exception ex)

            ////    {

            ////        Console.WriteLine(string.Format("Failed to authenticate with AAD by the credential with exception {0} and the stack trace {1}", ex.ToString(), ex.StackTrace));

            ////        throw new Exception("Failed to authenticate with AAD by the credential.");

            ////    }

            //}

 

            // Create and get JWT token

            return authenticationResult.CreateAuthorizationHeader();

        }

    }

}

You will also need to add Microsoft.IdentityModel.Clients.ActiveDirectory Nuget Package in this library project as you did in the previous one. Build the project and you can see the dll file is also created on a successful build.  

 

The final step: Create a .Net Framework Console Application  

Write the name of the project as “TestODataClient”.  

 

7.jpg

 
8.jpg

 

Now, we need to add the reference of the two library projects that we created before as shown below.  

 

9.jpg
Then in the program.cs file of TestODataClient console application.  

 
In the example program, the Program.cs class contains the main logic. It prints all customer group IDs  
present in the CustomerGroups entity.  
using AuthenticationUtility;
using Microsoft.Dynamics.DataEntities;
using Microsoft.OData.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AuthenticaitionUtility;

namespace TestODataClient
{
    class Program
    {
        public static string ODataEntityPath = ClientConfiguration.Default.UriString + "data";

        static void Main(string[] args)
        {

            Uri oDataUri = new Uri(ODataEntityPath, UriKind.Absolute);
            var context = new Resources(oDataUri);

            context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>(
            delegate (object sender, SendingRequest2EventArgs e)
            {
                //Add true in the parameter of GetAuthenticationHeader if you want to Authenticate with Client Secret
                //Add false in the parameter of GetAuthenticationHeader if you want to Authenticate with Client credentials (username, password)
                var authenticationHeader = OAuthHelper.GetAuthenticationHeader(true);
                e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
            });


            foreach (var customerGroup in context.CustomerGroups)
            {
                Console.WriteLine(customerGroup.CustomerGroupId);
 
            }

            Console.WriteLine("Code executed");
            Console.ReadLine();
        }
    }
}

Reference and credit:  

https://medium.com/@arif8h/consuming-odata-data-entities-of-d365f-o-using-odata-connected-service-in-net-9a457c1122ee