I rewrite this article from this link https://community.dynamics.com/ax/b/klaasdeforche/posts/forms-tutorial-resources-and-sysimageresources as it might be useful for some devs still work on legacy AX.
You can access these below resource from the forms at the bottom.
AX 4.0 forms\Tutorial_Resources
AX 2009 forms\SysImageResources
AX 2012 forms\SysImageResources
Thanks for reading!
My technical memo on Microsoft Dynamics 365 for Finance and Operations (formerly AX)
Thursday, November 21, 2019
Sunday, November 10, 2019
AX 2012 | get CompanyInfo and Vendor data through T-SQL
This post describes the table relation of Company and Vendor data written in T-SQL. In AX 2012, the information of Company and Vendor do not kept only in a single table, so this might be useful to understand their data model and relation.
Company Info
Vendors
Thanks for reading! Until the next post!
References
https://community.dynamics.com/ax/f/microsoft-dynamics-ax-forum/296010/companyinfo-table-in-ax-2012
https://community.dynamics.com/365/financeandoperations/b/goshoom/posts/queries-to-tables-with-inheritance
Company Info
select -- DPT.RecId as DPT_RecId --,DPL.RECID as DPL_RecId --,LPA.RecId as LPA_RecId DPT.DATAAREA ,DPT.NAME ,DPT.NAMEALIAS ,DPT.LANGUAGEID ,LPA.Street ,LPA.City ,LPA.ZipCode ,LPA.CountryRegionId --,DPT.PARTYNUMBER --,DPT.INSTANCERELATIONTYPE --,DPT.KNOWNAS --,DPT.PRIMARYADDRESSLOCATION --,DPT.PRIMARYCONTACTEMAIL --,DPT.PRIMARYCONTACTFAX --,DPT.PRIMARYCONTACTPHONE --,DPT.PRIMARYCONTACTTELEX --,DPT.PRIMARYCONTACTURL ,DPT.MODIFIEDDATETIME ,DPT.MODIFIEDBY ,DPT.CREATEDDATETIME ,DPT.CREATEDBY --,DPT.RECVERSION --,DPT.RELATIONTYPE --,DPT.PARTITION --,DPT.EDI_GLN from [dbo].[
DIRPARTYTABLE
] as DPT left outer join [dbo].[
DIRPARTYLOCATION
] as DPL on DPT.RecId = DPL.Party and DPT.PRIMARYADDRESSLOCATION = DPL.Location and DPL.IsPrimary = 1 left outer join [dbo].[
LOGISTICSPOSTALADDRESS
] as LPA on DPL.Location = LPA.Location and LPA.ValidFrom <= SYSDATETIME() and LPA.ValidTo >= SYSDATETIME() where DPT.INSTANCERELATIONTYPE = 41
Vendors
select -- VNT.RecId as VNT_RecId --,DPT.RECID as DPT_RecId --,DPL.RECID as DPL_RecId --,LPA.RecId as LPA_RecId --,TRE.RecId as TRE_RecId --,VBA.RecId as VBA_RecId VNT.DATAAREAID ,VNT.ACCOUNTNUM ,DPT.Name ,LPA.Street ,LPA.City ,LPA.ZipCode ,LPA.CountryRegionId ,TRE.RegistrationNumber as Tax_regist_num ,VBA.AccountId as Bank_ID ,VBA.Name as Bank_Name ,VBA.AccountNum as Bank_account_num ,VBA.SwiftNo as Bank_Swift_code ,VBA.BankIBAN as Bank_IBAN from [dbo].[
VENDTABLE
] as VNT left outer join [dbo].[
DIRPARTYTABLE
] as DPT on VNT.Party = DPT.RecId left outer join [dbo].[
DIRPARTYLOCATION
] as DPL on DPT.RecId = DPL.Party and DPT.PRIMARYADDRESSLOCATION = DPL.Location and DPL.IsPrimary = 1 left outer join [dbo].[
LOGISTICSPOSTALADDRESS
] as LPA on DPL.Location = LPA.Location and LPA.ValidFrom <= SYSDATETIME() and LPA.ValidTo >= SYSDATETIME() left outer join [dbo].[
TAXREGISTRATION
] as TRE on DPL.RecId = TRE.DirPartyLocation and TRE.ValidFrom <= SYSDATETIME() and TRE.ValidTo >= SYSDATETIME() left outer join [dbo].[
VENDBANKACCOUNT
] as VBA on VNT.AccountNum = VBA.VendAccount
Thanks for reading! Until the next post!
References
https://community.dynamics.com/ax/f/microsoft-dynamics-ax-forum/296010/companyinfo-table-in-ax-2012
https://community.dynamics.com/365/financeandoperations/b/goshoom/posts/queries-to-tables-with-inheritance
Tuesday, October 22, 2019
D365FO - OData simple test by Postman
From the blog series https://shootax.blogspot.com/2019/10/d365fo-data-integration-by-odata-part-1.html, we can also test OData by API tool i.e. Postman. This post describes how to configure and test it base on details mentioned in that series.
Register an app in AAD and white-list in D365FO
Again, we need to register an app. After finished, we should have these values.
Configure Postman
After install, do configure as follows.
Create a post request to get access token
Create a get request to test OData
That's all!
References:
https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/third-party-service-test
https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/services-home-page#register-a-web-application-with-aad
https://docs.microsoft.com/en-us/azure/active-directory/develop/app-registrations-training-guide
Register an app in AAD and white-list in D365FO
Again, we need to register an app. After finished, we should have these values.
- Application (client) ID
- Directory (tenant) ID
- Object ID
- Client secrets
Configure Postman
After install, do configure as follows.
Create a post request to get access token
Create a get request to test OData
That's all!
References:
https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/third-party-service-test
https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/data-entities/services-home-page#register-a-web-application-with-aad
https://docs.microsoft.com/en-us/azure/active-directory/develop/app-registrations-training-guide
Saturday, October 12, 2019
D365FO - Data integration by OData (Part 5 of 5)
D365FO - Data integration by OData (Part 1 of 5)
D365FO - Data integration by OData (Part 2 of 5)
D365FO - Data integration by OData (Part 3 of 5)
D365FO - Data integration by OData (Part 4 of 5)
D365FO - Data integration by OData (Part 5 of 5) You are here!
D365FO - Data integration by OData (Part 2 of 5)
D365FO - Data integration by OData (Part 3 of 5)
D365FO - Data integration by OData (Part 4 of 5)
D365FO - Data integration by OData (Part 5 of 5) You are here!
Create OData client application
Finally, here's the last of this series.
We will create OData client with AuthenticationUtility and ODataUtility we already made.
Create OData client
First, we create a C# console application project. Name it as 'TestODataClient'.
Next, add the following reference.
Then, write the following code in Program.cs file.
Now, rebuild the project, run and if anything goes well, then get the following result.
Finally, check the update through the table and OData with the same way from the Part 1.
Finally, the data is inserted successfully from the external application into D365FO!
That's all! Thanks for reading!
References
We will create OData client with AuthenticationUtility and ODataUtility we already made.
Create OData client
First, we create a C# console application project. Name it as 'TestODataClient'.
Next, add the following reference.
- AuthenticationUtility
- ODataUtility
- Microsoft.OData.Client
Then, write the following code in Program.cs file.
using AuthenticationUtility;
using ODataUtility.Microsoft.Dynamics.DataEntities;
using Microsoft.OData.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestODataClient
{
class Program
{
public static string ODataEntityPath = ClientConfiguration.Default.UriString + "data";
public static void CreateMyCar(Resources context)
{
string CarID = "C0001";
DateTime todayDateTime = new DateTime(2019, 10, 11, 0, 0, 0);
DateTimeOffset todayDateTimeOffset = new DateTimeOffset(todayDateTime, new TimeSpan(+1, 0, 0));
decimal amount = 499999.99m;
try
{
MyCar MyCarEntity = new MyCar();
DataServiceCollection<MyCar> MyCarCollection = new DataServiceCollection<MyCar>(context);
MyCarCollection.Add(MyCarEntity);
MyCarEntity.CarID = CarID;
MyCarEntity.BrandName = "Suzuki";
MyCarEntity.SerieName = "Swift";
MyCarEntity.Color = "Black";
MyCarEntity.Price = amount;
MyCarEntity.PurchasedDate = todayDateTimeOffset;
context.SaveChanges(SaveChangesOptions.PostOnlySetProperties | SaveChangesOptions.BatchWithSingleChangeset);
Console.WriteLine(string.Format("My car record {0} - created !", CarID));
}
catch (DataServiceRequestException e)
{
Console.WriteLine(string.Format("My car record {0} - failed !", CarID));
}
}
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)
{
var authenticationHeader = OAuthHelper.GetAuthenticationHeader();
e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
});
CreateMyCar(context);
Console.ReadLine();
}
}
}
Now, rebuild the project, run and if anything goes well, then get the following result.
Finally, check the update through the table and OData with the same way from the Part 1.
Table
Finally, the data is inserted successfully from the external application into D365FO!
That's all! Thanks for reading!
References
- Rahul Mohta, Yogesh Kasat and JJ Yadav, Implementing MS Dynamics 365 for Finance and Operations, First published Sep 2017 (book)
- Simon Buxton, Extending MS Dynamics 365 for Operations Cookbook, First published May 2017 (book)
- Deepak Agarwal and Abhimanyu Singh, Dynamics 365 for Finance and Operations Development Cookbook, Fourth Edition Aug 2017 (book)
- https://github.com/OData/odata.net/issues/1220
D365FO - Data integration by OData (Part 4 of 5)
D365FO - Data integration by OData (Part 1 of 5)
D365FO - Data integration by OData (Part 2 of 5)
D365FO - Data integration by OData (Part 3 of 5)
D365FO - Data integration by OData (Part 4 of 5) You are here!
D365FO - Data integration by OData (Part 5 of 5)
Create ODataUtility
First, we create a C# console application project. Name it as 'ODataUtility'.
Next, use 'Manage NuGet Packages...' to add the following reference.
Then, at Visual Studio go to Tools -> Extensions and Updates and search by 'OData Client code'.
Download and install 'OData v4 Client Code Generator'.
Next, add a 'ODataClient.tt' OData Client into the project.
You can click here OK or Cancel. If click ok, it means the first time it generates without the MetadataDocumentUri. The result will be the same eventually.
Then we put this value https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/$metadata to the MetadataDocumentUri
Before
After
Then, save ODataClient.tt file, and now it's time to click OK and generate the template (proxy classes).
**Tip: The generate process take few seconds, do not interrupt Visual Studio before the generating finished.
The new created template is ODataClient.cs with around 70 MB file size.
So, the last step is to build the project.
Actually, we should get it finish here, however there are some bug from OData V4 client code generator including the problem that the current version of Visual studio in OneBox machine is VS 2015 which cannot handle such a huge file like ODataClient.cs.
So, when we build the project, we get the error message as follows.
Error CS8103 Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals.
**Thanks toryb comment from this link https://github.com/OData/odata.net/issues/1220 His method works and very useful!
Here is my workaround guideline as per toryb's comment.
1. Close Visual Studio.
2. Copy ODataClient.cs file from VS project folder to another place.
3. Do backup that file in your own way.
4. Open ODataClient.cs by your desired text editor.
5. Search and list with 'Edmx' keyword.
You will find that area of Edmx variable are between line 50,995th and 325,713th !!
6. Cut the XML part (start at <edmx:Edmx... and ...</edmx:Edmx> at the end) and paste to the new file.
7. In the new file, replace all "" (2 double quote) with " (single double quote) because they were generated incorrectly. This step will take some minutes.
8. Save edmx.xml file.
9. Back to ODataClient.cs file, put the file name as the value of Edmx variable like this.
private const string Edmx = @"edmx.xml";
10. Search by 'CreateXmlReader' keyword and create an additional overload of CreateXmlReader() that does not take any parameters as follows.
Before
After
11. Replace global::System.Xml.XmlReader reader = CreateXmlReader(Edmx);
with global::System.Xml.XmlReader reader = CreateXmlReader();
12. Save ODataClient.cs file.
13. Copy ODataClient.cs and Edmx.xml back to VS project folder.
14. Launch Visual Studio
15. Add Edmx.xml file into the project and update it's Build Action is "Content" and the Copy to Output Directory is set to "Copy if Newer" or "Copy Always". This will make sure the xml file is distributed with the library / application.
So now, rebuild the project again. And the result should be ok as follows.
=== End of Part 4 ===
D365FO - Data integration by OData (Part 2 of 5)
D365FO - Data integration by OData (Part 3 of 5)
D365FO - Data integration by OData (Part 4 of 5) You are here!
D365FO - Data integration by OData (Part 5 of 5)
Create OData client application
So now, it's time to create ODataUtility.
Why we need this?
This utility will help us to generate all exposed OData service endpoints in D365FO (including one we created before) to be the proxy classes. Then we can connect to those D365FO data entities easily by C# code.
Why we need this?
This utility will help us to generate all exposed OData service endpoints in D365FO (including one we created before) to be the proxy classes. Then we can connect to those D365FO data entities easily by C# code.
Create ODataUtility
First, we create a C# console application project. Name it as 'ODataUtility'.
Next, use 'Manage NuGet Packages...' to add the following reference.
- Microsoft.IdentityModel.Clients.ActiveDirectory
- Microsoft.OData.Client
Then, at Visual Studio go to Tools -> Extensions and Updates and search by 'OData Client code'.
Download and install 'OData v4 Client Code Generator'.
Next, add a 'ODataClient.tt' OData Client into the project.
You can click here OK or Cancel. If click ok, it means the first time it generates without the MetadataDocumentUri. The result will be the same eventually.
Then we put this value https://usnconeboxax1aos.cloud.onebox.dynamics.com/data/$metadata to the MetadataDocumentUri
Before
After
Then, save ODataClient.tt file, and now it's time to click OK and generate the template (proxy classes).
**Tip: The generate process take few seconds, do not interrupt Visual Studio before the generating finished.
The new created template is ODataClient.cs with around 70 MB file size.
So, the last step is to build the project.
Actually, we should get it finish here, however there are some bug from OData V4 client code generator including the problem that the current version of Visual studio in OneBox machine is VS 2015 which cannot handle such a huge file like ODataClient.cs.
So, when we build the project, we get the error message as follows.
Error CS8103 Combined length of user strings used by the program exceeds allowed limit. Try to decrease use of string literals.
**Thanks toryb comment from this link https://github.com/OData/odata.net/issues/1220 His method works and very useful!
Here is my workaround guideline as per toryb's comment.
1. Close Visual Studio.
2. Copy ODataClient.cs file from VS project folder to another place.
3. Do backup that file in your own way.
4. Open ODataClient.cs by your desired text editor.
5. Search and list with 'Edmx' keyword.
You will find that area of Edmx variable are between line 50,995th and 325,713th !!
6. Cut the XML part (start at <edmx:Edmx... and ...</edmx:Edmx> at the end) and paste to the new file.
7. In the new file, replace all "" (2 double quote) with " (single double quote) because they were generated incorrectly. This step will take some minutes.
8. Save edmx.xml file.
9. Back to ODataClient.cs file, put the file name as the value of Edmx variable like this.
private const string Edmx = @"edmx.xml";
10. Search by 'CreateXmlReader' keyword and create an additional overload of CreateXmlReader() that does not take any parameters as follows.
Before
After
11. Replace global::System.Xml.XmlReader reader = CreateXmlReader(Edmx);
with global::System.Xml.XmlReader reader = CreateXmlReader();
12. Save ODataClient.cs file.
13. Copy ODataClient.cs and Edmx.xml back to VS project folder.
14. Launch Visual Studio
15. Add Edmx.xml file into the project and update it's Build Action is "Content" and the Copy to Output Directory is set to "Copy if Newer" or "Copy Always". This will make sure the xml file is distributed with the library / application.
So now, rebuild the project again. And the result should be ok as follows.
=== End of Part 4 ===
D365FO - Data integration by OData (Part 3 of 5)
D365FO - Data integration by OData (Part 1 of 5)
D365FO - Data integration by OData (Part 2 of 5)
D365FO - Data integration by OData (Part 3 of 5) You are here!
D365FO - Data integration by OData (Part 4 of 5)
D365FO - Data integration by OData (Part 5 of 5)
Create AuthenticationUtility
First, we create a C# class library project. Name it as 'AuthenticationUtility'.
Next, use 'Manage NuGet Packages...' to add the following reference.
**Some references will be used in several projects, so make sure the references version consistent on all projects.
Then, add a 'ClientConfiguration' class into the project with the following code.
Check and change Tenant and Client App ID.
Next, add a 'OAuthHelper' class into the project with the following code.
Here we use the URI which already registered in AAD the previous blog.
After all, build the project. We should get the good result with AuthenticationUtitlity.dll which will be used by OData client in the further step.
=== End of Part 3 ===
D365FO - Data integration by OData (Part 2 of 5)
D365FO - Data integration by OData (Part 3 of 5) You are here!
D365FO - Data integration by OData (Part 4 of 5)
D365FO - Data integration by OData (Part 5 of 5)
Create OData client application
There are 3 main steps:
- Create AuthenticationUtility (C# class library)
- Create ODataUtitlity (C# console application)
- Create OData client (C# console application)
Create AuthenticationUtility
First, we create a C# class library project. Name it as 'AuthenticationUtility'.
Next, use 'Manage NuGet Packages...' to add the following reference.
- Microsoft.IdentityModel.Clients.ActiveDirectory
**Some references will be used in several projects, so make sure the references version consistent on all projects.
Then, add a 'ClientConfiguration' class into the project with the following code.
Check and change Tenant and Client App ID.
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() { UriString = "https://usnconeboxax1aos.cloud.onebox.dynamics.com/", ActiveDirectoryResource = "https://usnconeboxax1aos.cloud.onebox.dynamics.com", ActiveDirectoryTenant = "https://login.windows.net/
*****
.onmicrosoft.com", ActiveDirectoryClientAppId = "
*****
", }; public string UriString { get; set; } public string ActiveDirectoryResource { get; set; } public String ActiveDirectoryTenant { get; set; } public String ActiveDirectoryClientAppId { get; set; } } }
Next, add a 'OAuthHelper' class into the project with the following code.
Here we use the URI which already registered in AAD the previous blog.
using
Microsoft.IdentityModel.Clients.ActiveDirectory
; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace AuthenticaitionUtility { public class OAuthHelper { /// <summary> /// The header to use for OAuth. /// </summary> 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 = false) { string aadTenant = ClientConfiguration.Default.ActiveDirectoryTenant; string aadClientAppId = ClientConfiguration.Default.ActiveDirectoryClientAppId; string aadResource = ClientConfiguration.Default.ActiveDirectoryResource; AuthenticationResult authenticationResult; var authenticationContext = new AuthenticationContext(aadTenant, TokenCache.DefaultShared); authenticationResult = authenticationContext.AcquireTokenAsync(aadResource, aadClientAppId, new Uri("
https://MyCar
"), new PlatformParameters(PromptBehavior.Auto)).Result; // Create and get JWT token return authenticationResult.CreateAuthorizationHeader(); } } }
After all, build the project. We should get the good result with AuthenticationUtitlity.dll which will be used by OData client in the further step.
=== End of Part 3 ===
Subscribe to:
Posts (Atom)