Showing posts with label D365 FO. Show all posts
Showing posts with label D365 FO. Show all posts

Saturday, April 19, 2025

Error at "using Microsoft.IdentityModel.Clients.ActiveDirectory" in D365FO update 10.0.43

 If you used Azure Active Directory Authentication Library (ADAL) in your customization, and get a compilation error at "using Microsoft.IdentityModel.Clients.ActiveDirectory" statement in 10.0.43 update, this is because ADAL is deprecated and MS have removed the reference from the AOT. 

You will need to migrate your code to Microsoft Authentication Library (MSAL).

In order to do that, you will need to add the Microsoft.Identity.Client.dll library to your bin-folder (can be found in other subfolders under K:\AosService\PackagesLocalDirectory), and add a corresponding reference to a VS project. The reference will then be created as an XML-file. Both the DLL and the XML files must be added to source control via "Add Items to Folder...", like this:

K:\AosService\PackagesLocalDirectory\<package name>\bin\Microsoft.Identity.Client.dll

K:\AosService\PackagesLocalDirectory\<package name>\<model name>\AxReference\Microsoft.Identity.Client.xml

Then, you will need to change the code.

Before:

using Microsoft.IdentityModel.Clients.ActiveDirectory;


            ClientCredential clientCrendential = new ClientCredential(clientId, clientSecret);
            AuthenticationContext authContext = new AuthenticationContext(authority);
            AuthenticationResult authResult = authContext.AcquireToken(resource, clientCrendential);
            accessToken = authResult.AccessToken;


After change, it will be like this:

using Microsoft.Identity.@Client;


            ConfidentialClientApplicationBuilder clientApplicationbuilder = ConfidentialClientApplicationBuilder::Create(clientId);

            IConfidentialClientApplication app = clientApplicationbuilder.WithClientSecret(clientSecret).WithAuthority(authority).Build();

            System.Collections.Generic.List<System.String> scopes = new System.Collections.Generic.List<System.String>();

            scopes.Add(resource + '/.default');

            System.Collections.IEnumerable enumerable = scopes;

            AcquireTokenForClientParameterBuilder parameterBuilder = app.AcquireTokenForClient(enumerable);

            var task = parameterBuilder.ExecuteAsync();

            task.Wait();

            AuthenticationResult authResult = task.Result;

            accessToken = authResult.AccessToken;



Here is the code to test the above written code and generate token using X++ job:

public static void main(Args _args)

{

    str clientId            = 'xxxxxxxxxxxxxxxxxxxx'; 
    str clientSecret     = 'xxxxxxxxxxxxxxxxxxxx'; 
    str resource          =  '<EnvironmentId>';
    str tenant             = 'xxxxxxxxxxxxxxxxxxxx';

    //Before

    //Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext context;
    //Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential credential;
    //Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult result;
    //str accessToken;
    //context = new Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.microsoftonline.com/"+ tenant +"/oauth2/token");
    //credential = new Microsoft.IdentityModel.Clients.ActiveDirectory.ClientCredential(clientId, clientSecret);
    //result = context.AcquireToken(resource, credential);
    //accessToken = result.AccessToken;
    //info(accessToken);

    //After

    ConfidentialClientApplicationBuilder clientApplicationbuilder = ConfidentialClientApplicationBuilder::Create(clientId);
    IConfidentialClientApplication app = clientApplicationbuilder.WithClientSecret(clientSecret).WithAuthority("https://login.microsoftonline.com/"+ tenant +"/oauth2/token").Build();
    str accessToken;
    System.Collections.Generic.List<System.String> scopes = new System.Collections.Generic.List<System.String>();
    scopes.Add(resource + '/.default');
    System.Collections.IEnumerable enumerable = scopes;
    AcquireTokenForClientParameterBuilder parameterBuilder = app.AcquireTokenForClient(enumerable);
    var task = parameterBuilder.ExecuteAsync();
    task.Wait();
    AuthenticationResult authResult = task.Result;
    accessToken = authResult.AccessToken;
    info(accessToken);

}


Note: where resource is enviornment url in both cases.

Sunday, April 2, 2023

Create URL for specific record in D365FO using X++

To create a URL for a specific record, you'll need to know the unique identifier for that record. This could be a record ID, a customer number, or some other unique identifier that you use in your system.

Once you have the unique identifier, you can create a URL that includes that identifier. Here's an example:

Let's say you have a customer with the ID "12345". To create a URL for that customer, you could use the following code:



You can use this same code to create URLs for other types of records as well. Just replace "AccountNum" with the unique identifier for the record you want to link to.


Done!

Sunday, February 6, 2022

SysOperation Framework in D365FO

The SysOperation Framework, initially called Business Operation Framework, seem to be the new substitute of the RunBase framework. As such, it allows you to perform operations that require parameters from the user, it allows you to set the operations to be executed in batch, or in a new asynchronous way, or in a synchronous manner. The great thing is that it simplifies the pack / unpack of variables that was pretty nasty in the RunBase framework, taking advantage of the Attributes feature, introduced with AX 2012.

SysOperation framework allows application logic to be written in a way that supports running operations interactively or via the Microsoft Dynamics AX batch server. It implements the MVC (Model–View–Controller) design pattern, with the isolation of Parameters (Model), Dialog (View) and Service (Controller), for the code that’s executed.

The key objects of the framework are defined below:

  • DataContract
  • UIBuilder
  • Controller
  • Service


DataContract:

The data contract is the model class in which we define which attributes we need for our operation, commonly set as parameters by the user in a dialog. It's nothing more than a model class with a few attributes in it. We can define a SysOperation Data Contract class simply by adding the DataContractAttribute attribute to its declaraion. 

Additionally, if we want a set of methods to be available to us, we can also extend the SysOperationDataContractBase base class. With this class, we can define how our basic dialog will look like to the user. 

We can define labels, groups, sizes and types of the parameters.


UIBuilder:

The UI builder class is actually an optional class for the SysOperation framework, which kind of acts as the view part of the pattern. You should only use it if you want to add some extra behavior to the dialog that AX constructs dynamically for you. If you are perfectly happy with the dialog AX shows you when you run your operation, you shouldn't worry about this class. To create a UI Builder, you should extend the SysOperationAutomaticUIBuilder class. It will provide you a set of methods to work with the dialog's design, but we usually add extra behavior or customize a lookup inside the postBuild method.


Controller:

The controller class has greater responsibility than the others. As the name suggests, it is the class that orchestrates the whole operation. The controller class also holds information about the operation, such as if it should show a progress form, if it should show the dialog, and its execution mode - asynchronous or not. To create a controller class you should extend the SysOperationServiceController, which will give you all of the methods you need.


Service:

There are some who put the business logic on controller classes so that they also perform the operation itself. I'm particularly not a big fan of that, it's too much responsibility for a single class! The programmers who created the SysOperation framework probably think the same, and they have made a way to separate the operation. You can create a service class! The only thing you have to do is extend the SysOperationServiceBase class and you're good to go. This class is the one that should contain all the business logic. When constructing your controller, you will indicate which class holds the operation that the controller will trigger, I'll demonstrate it later.

So this was a brief explanation of SysOperation framework . For more information, you can also download the official Microsoft whitepaper here.

Now, Let's have a look on sysoperation framework with the help of an example:

DataContract Class:

UI Builder:

  


Controller:


Service:


In the last, create a new action menu item that will call the controller class. So in the properties of action menu item  set the 'Object type' to be class and the 'object' to be name of the controller class. In my example, the controller class is named "DemoController".

Here is a screenshot of dialog box from the above UI Builder class defined by single and multiselect parameters.






































It's Done ☺

Thursday, December 2, 2021

No print management settings are applicable so no document is produced

 Getting error message while printing report that  "No print management settings are applicable so no document is produced."



Solution:

Go to that module --> Setup > Forms > Form setup > General tab > Print management 

Right click and create new for all the reports you want to print.




Done.

Friday, July 2, 2021

Access D365 FO Local VM Environment URL from your machine

Today, we will see how we can access D365FO Local VM URL from your machine.

First Find the host file of your machine from the following path: C:\Windows\System32\drivers\etc

Your host file looks like:


Lets assume your local Environment IP address is 182.10.10.17

Once you find the host file, open the file and replace the local host IP address with the local environment IP address. After that, add a line having IP address with URL of local Environment at the bottom.

Your host file looks like:


Now, open internet explorer in your machine and enter the above URL. It worked!


Note: If there is any VPN required to access your local environment then make sure your VPN is connected.


:) 


Wednesday, June 30, 2021

Error importing database: Could not read schema model header information from package. The model version '3.6' is not supported

Error:

Error importing database: Could not read schema model header information from package. The model version '3.6' is not supported.




In order to fix this issue, you need to download and install the latest Data Tier Application Framework(18.2).

(Here is the link: https://www.microsoft.com/en-us/download/confirmation.aspx?id=58207)


After installed the latest Framework, open command prompt as administrator and write the below command:

C:\Program Files\Microsoft SQL Server\150\DAC\bin>SqlPackage.exe /Action:import /Sourcefile:"C:\temp\UATDataBasebackup.bacpac" /tsn:localhost /tdn:AxDB_New /p:CommandTimeout="0"


It worked.


Friday, May 21, 2021

Get Reference of Original Sales Order from Credit Note Sales Order using X++

If you create new sales order and create credit note of any previous sales order, then here is the way to find reference of previous sales order (invoice number) through newly created credit note sales order using x++.

InventTransOrigin::findByInventTransId(SalesLine::Find(this.SalesId).InventTransIdReturn).ReferenceId;


Note:
If you create a credit note simply by using the "Credit Note" button on the sales order form, Ax copies the previous invoice lines into the original sales order with a negative sign. In this case you do not need any additional reference to the original sales order as you are still using the same sales order.

Sunday, February 21, 2021

Import backpac file to Sql Server

Here are the steps below to imort the .bacpac file to the sql server.
Every time you import the .bacpac file, it will always create a new database on the sql server.

Step-1: Run command prompt as administrator and write the following command in it.

"C:\Program Files (x86)\Microsoft SQL Server\140\DAC\bin\SqlPackage.exe" /Action:Import /SourceFile:"J:\AXDB_UAT.bacpac" /tsn:dev630a58c756-1  /tdn:SSProd /p:CommandTimeout="0"

Here:
tsn is target server name
tdn is target database name
New database created successfully here.

Step-2: Now rename previous database and set newly created database named as "AxDB" after stopped following services.

World wide web publishing service
Management Reporter 2012 process service
Microsoft Dynamics 365 Unified Operations: Batch Management Service
Microsoft Dynamics 365 Unified Operations: Data Import Export Framework Service                                                                                                      
                                                                                       OR

you can rename the database by using following commands:

Set database to single user 
ALTER DATABASE dbName
SET SINGLE_USER WITH ROLLBACK IMMEDIATE 

Rename database
ALTER DATABASE dbName MODIFY NAME = dbNewName

Set database back to multiuser
ALTER DATABASE dbName
SET MULTI_USER WITH ROLLBACK IMMEDIATE

Step-3: Start the following services  

World wide web publishing service
Management Reporter 2012 process service
Microsoft Dynamics 365 Unified Operations: Batch Management Service
Microsoft Dynamics 365 Unified Operations: Data Import Export Framework Service    

Step-4: Now run db sync using the below command

K:\> AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe -bindir "K:AosService\PackagesLocalDirectory" -metadatadir K:AosService\PackagesLocalDirectory -sqluser username  -sqlserver sqlservername  -sqldatabase AxDB -setupmode sync -syncmode fullall -isazuresql false -sqlpwd password

Done!



Friday, January 22, 2021

The required assembly 'Microsoft.Dynamics.Framework.Tools.ApplicationExplorer.dll' does not exists.

I was applying the latest Platform update to one of our internal server when I got this error.

Error:

"The required assembly 'Microsoft.Dynamics.Framework.Tools.ApplicationExplorer.dll' does not exists."




Solution:

To solve this error, just copied the dll file to the location where it popped up and that's it. Now, run the step again and the issue is resolved. 
(Hint: you can search this dll file in that drive where VS is installed).


Friday, January 8, 2021

Enable maintenance mode on local VM in D365FO

I found the following warning message while creating/activating new financial dimension on Local VM in d365 FO. For resolving this issue put environment on maintenance mode.


OR




In order to put environment in maintenance mode follow these steps:

1. Run Command prompt as administrator.

2. Execute this command

C:\AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe --metadatadir C:\AosService\PackagesLocalDirectory --bindir C:\AosService\PackagesLocalDirectory\Bin --sqlserver . --sqldatabase axdb --sqluser AOSUser --sqlpwd AOSWebSite@123 --setupmode maintenancemode --isinmaintenancemode true 


3. Restart AOS service from IIS

4. Now, Create/Activate financial dimension or  do the changes that you want. once you done. Revert back to environment in normal mode by using this command.

C:\AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe --metadatadir C:\AosService\PackagesLocalDirectory --bindir C:\AosService\PackagesLocalDirectory\Bin --sqlserver . --sqldatabase axdb --sqluser AOSUser --sqlpwd AOSWebSite@123 --setupmode maintenancemode --isinmaintenancemode false



Done :) 

Friday, January 1, 2021

Apply platform version update to Local VM of D365FO

Here are the following steps to update local VM of D365FO to latest version.

1. Go to LCS: https://lcs.dynamics.com/
2. Click on the Shared Asset Library button OR you can go to Asset Library of Project
3. Select Software deployable package and download latest update (you can also view details of package from right side).
4. After download move package to any folder (create new folder) of  C drive where local VM is setup
5. Make sure to unblock zip file from properties before extract deployable package to folder
6. After extract deployable package to folder open Command Prompt (cmd) with administrator in that folder.

Close all the instance of Visual Studio. Now run the following command one by one with sequence

i. AXUpdateInstaller.exe generate -runbookid="OneBoxDev" -topologyfile="DefaultTopologyData.xml" -servicemodelfile="DefaultServiceModelData.xml" -runbookfile="OneBoxDev-runbook.xml" 

ii. AXUpdateInstaller.exe import -runbookfile=OneBoxDev-runbook.xml (In this step it may ask Y/N, then press Y/y)

iii. AXUpdateInstaller.exe execute -runbookid=OneBoxDev

It will take approximatly 2 hours to complete 17 steps. Once its completed, open the environment and you will see that its updated. Enjoy :)

Thursday, December 31, 2020

Get financial dimension display value using x++

 Code to get dimension display value in ax 2012/D365 FO using x++ 


public str getDimensionDisplayValue(RecId _defaultDimension, Name dimName)
{
  DimensionAttributeValueSetStorage dimStorage;

  dimStorage = DimensionAttributeValueSetStorage::find(_defaultDimension);
  return dimStorage.getDisplayValueByDimensionAttribute(DimensionAttribute::findByName(dimName).RecId);
}
str dimensionValue;
dimensionValue = this.getDimensionDisplayValue(DefaultDimensionRecId, 'Project');

//Where
//defaultDimensionRecId can be PurchTable.Defaultdimension, InventTable.DefaultDimension etc
//'Project' is the name of the financial dimension. It can be 'BusinessUnit' 'CostCenter' etc.


Note: Please refer to the tables below to get display value name.
1. DimensionfinancialTagCtegory
2. OmoperatingUnit (OMOperatingUnitNumber, OMOperatingUnitType)


Tuesday, December 15, 2020

Get active financial dimensions in ax 2012 or D365 using x++

Below is the code to get active financial dimension in ax 2012 or D365 using x++


          DimensionAttributeSetItem  dimAttrSetItem;
          DimensionAttribute  dimAttr;
          DimensionEnumeration dimensionSetId;

          int dimAttrCount;

          dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger();

//Code to get count of active dimensions 

           select count(RecId) from dimAttr
                       where dimAttr.Type != DimensionAttributeType::MainAccount
                 join RecId from dimAttrSetItem
                        where dimAttrSetItem.DimensionAttribute == dimAttr.RecId &&
                                   dimAttrSetItem.DimensionAttributeSet == dimensionSetId;

               info(strFmt("Total active financial dimensions for current legal entity: %1", dimAttr.RecId));

//Code to get active dimensions name

            while select * from dimAttr
                           order by Name
                           where dimAttr.Type != DimensionAttributeType::MainAccount
                     join RecId from dimAttrSetItem
                           where dimAttrSetItem.DimensionAttribute == dimAttr.RecId &&
                                      dimAttrSetItem.DimensionAttributeSet == dimensionSetId        
            {

                    info(dimAttr.Name);

             }


Enjoy :) 

Monday, December 14, 2020

Sync single table in ax 2012 or D365 FO using X++

 Sync a table in ax 2012 or  D365FO using x++.

Create a job in ax 2012 or runnable class in D365FO. Write the following piece of code in it and run the job.


appl.dbSynchronize(tableNum(TableName));


Wednesday, November 11, 2020

D365 FO :- Unable to connect to the remote server at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy,

 I got following exception while running report in D365 FO.


Unable to connect to the remote server at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T](RESTCommand`1 cmd, IRetryPolicy policy, OperationContext operationContext) at Microsoft.WindowsAzure.Storage.Table.CloudTable.Exists(Boolean primaryOnly, TableRequestOptions requestOptions, OperationContext operationContext) at Microsoft.WindowsAzure.Storage.Table.CloudTable.CreateIfNotExists(TableRequestOptions requestOptions, OperationContext operationContext) at Microsoft.DynamicsOnline.Infrastructure.Components.TableAccessor.TableStorageAccessor.PerformOperation(CloudStorageAccount storageAccount, String tableName, Func`1 operation) at Microsoft.DynamicsOnline.Infrastructure.Components.TableAccessor.TableStorageAccessor.AddRecord[T](........................



After searching, I found that this exception occurs when the Store Emulator is not running. Therefore, you have to start it. Perform the following step to start Store Emulator.

  1. Open Command Prompt as administrator.
  2. Now go to "C:\Program Files (x86)\Microsoft SDKs\Azure\Storage Emulator> AzureStorageEmulator.exe start.




Saturday, March 28, 2020

The option 4 for querystore query_capture_mode is not supported



It is caused due to a setup mismatch between AzureSQL and SQL server. To solve this issue you have to run this SQL statement
ALTER DATABASE [QueryStoreDB] SET QUERY_STORE (QUERY_CAPTURE_MODE = ALL); in the Azure SQL (UAT) environment before you export the database.
Other solution is: 
The solution is to rename the bacpac file to zip, extract the content and locate the "model.xml" file. Copy the "model.xml" file to a new location where you can locate it easily. Rename the zip file back to bacpac. Edit the "model.xml" file:
From:
<Property Name="QueryStoreCaptureMode" Value="4" />
To:
<Property Name="QueryStoreCaptureMode" Value="2" />
Save the "model.xml" file.
Now you need to use the "/ModelFilePath" parameter of SqlPackage.exe, and point it to your updated "model.xml" file. This will instruct the SqlPackage.exe to read the updated "model.xml" file and ignore the one from within the bacpac file.
After adding /ModelFilePath parameter of SqlPackage.exe, the command will look like this: 
C:\>"Program Files (x86)\Microsoft SQL Server\140\DAC\bin\SqlPackage.exe" /Action:Import /SourceFile:"bacpacfile" /mfp:"modelfilepath" /tsn:servername /tdn:dbname /p:CommandTimeout=1200

Wednesday, March 25, 2020

Copy Data of Custom fields from PurchLine to PurchaseOrderVersions


  1. Add fields by using table extensions to the PurchLine and PurchLineHistory tables.
  2. Create a new table map containing the fields that must be copied. 
  3. Implement the new table map on the two new table extensions.
  4. Create a new class to implement the PurchLineIVersioningFieldSet interface and implement the following required methods.
    • copyVersion method - Copies data between two records of the new table map type.
    • fieldSetTableMapId method - Returns the ID of the new table map.
    • isChangeConfirmationRequired method - Returns true or false based on whether the change to the newly added field values requires a confirmation to be created.
  5. Now run build + sync.

Customization Analysis Report (CAR) OR Check BP error using cmd in ax d365

Open command prompt as administrator and write below command to check BP error or car.



K:\AosService\PackagesLocalDirectory\bin\xppbp.exe -metadata=K:\AosService\PackagesLocalDirectory -all -model="ApplicationSuite" -xmlLog=C:\temp\BPCheckLogcd.xml -module="ApplicationSuite" -car=c:\temp\BPReport.xlsx

where ApplicationSuite = "YourModelName"

It will create an xml file named (BPCheckLodcd.xml) and excel file named (BPReport.xlsx) at location C:\temp. You can change this path according to you. This report is called Customization Analysis Report (CAR).

Monday, March 23, 2020

Run db sync using cmd in ax d365

Here is the command to run db sync using cmd in ax d365. Open command prompt as administrator and write the below code.

K:\> AosService\PackagesLocalDirectory\Bin\Microsoft.Dynamics.AX.Deployment.Setup.exe  -bindir "K:AosService\PackagesLocalDirectory"  -metadatadir K:AosService\PackagesLocalDirectory -sqluser username  -sqlserver  serverName  -sqldatabase databasename -setupmode sync -syncmode fullall -isazuresql false -sqlpwd pswd