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.
Step 2: Now, go to Extensions and then manage Extensions. Install OData-connected service.
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.
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.
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”.
Now, we need to add the reference of the two library projects that we created before as shown below.
Program.cs
class contains the main logic. It prints all customer group IDsCustomerGroups 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
Comments
Post a Comment