D365 F&O DBSync Error – ##[error]SYNCENGINE(0,0): Error Number: -2,State:0,Class:11

Summary:

 
While working with the D365 F&O build server, we suddenly started to get the timeout error on the database synchronization step. Checking the logs on the azure dev ops pointed out that, db sync was not able to complete the login phase for the sql server. 
 
This was odd, as the builds have been working fine until this point. This was a wild goose chase to check the settings of the sql server, hosts file, testing pings etc …
 

Build failed:

2020-02-23_14-54-38
 
This started happening after we took 10.0.8 quality update, or it was co-incidence – we are not sure yet.
 
Update 2/23/2020 10:15 PM CST:
 
  • Update a development machine (not a build) with the same updates and the auto close was false – so hopefully it was an one off. This is good !!! 🙂

Resolution:

 
It came down to the “Auto close” was set to “True”, after changing that to “False”, we can see that now builds are getting done successfully.
 
Some readings/ view on auto close feature in sql server
 
 
The hints pointed to to look at auto close were as:
 
  • DBCC Check was running again and again the AxDB, which normally shoudn’t happen.
  • It was seen that AxDB start event was coming in the Application logs too frequently. 
 
Hopefully it will help other folks as well, if such error is seen in the logs.
 
You can do this by SSMS UI or using following command on a database:
 
ALTER DATABASE [AxDB] SET AUTO_CLOSE OFF;
 
2020-02-23_15-04-32
 

Full error:

 
Build started 2/23/2020 4:06:12 PM.
Project “C:\DynamicsSDK\Metadata\SyncEngine.proj” on node 1 (default targets).
SyncEngine:
Database synchronization…
– Metadata binaries: K:\AosService\PackagesLocalDirectory
– Synchronization mode: fullall
K:\AosService\PackagesLocalDirectory\Bin\SyncEngine.exe -syncmode=fullall -metadatabinaries=K:\AosService\PackagesLocalDirectory -connect=”Data Source=BUILD-1;Initial Catalog=AxDB;Integrated Security=True;Enlist=True;Application Name=SyncEngine” -fallbacktonative=False -raiseDataEntityViewSyncNotification
System.Data.SqlClient.SqlException (0x80131904): Connection Timeout Expired. The timeout period elapsed during the post-login phase. The connection could have timed out while waiting for server to complete the login process and respond; Or it could have timed out while attempting to create multiple active connections. The duration spent while attempting to connect to this server was – [Pre-Login] initialization=3; handshake=5; [Login] initialization=0; authentication=2; [Post-Login] complete=14746; —> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData, DbConnectionPool pool, String accessToken, Boolean applyTransientFaultHandling, SqlAuthenticationProviderManager sqlAuthProviderManager)
##[error]SYNCENGINE(0,0): Error Number: -2,State:0,Class:11
SYNCENGINE : error Number: -2,State:0,Class:11 [C:\DynamicsSDK\Metadata\SyncEngine.proj]
at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions)
at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection)
at System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions)
at System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry)
at System.Data.SqlClient.SqlConnection.Open()
at Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.RetryPolicy.<>c__DisplayClass1.b__0()
at Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.RetryPolicy.ExecuteAction[TResult](Func`1 func)
at Microsoft.Dynamics.AX.Data.Sql.SqlDataAccessManager.OpenConnection(SqlConnection conn)
at Microsoft.Dynamics.AX.Data.Sql.SqlDataAccessManager.ExecuteSql[T](SqlCommand cmd, Func`2 sqlFunc)
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Microsoft.Dynamics.AX.Data.Sql.SqlDataAccessManager.HandleException(ExceptionDispatchInfo edi, SqlExecutionInfo execInfo)
at Microsoft.Dynamics.AX.Data.Sql.SqlDataAccessManager.ExecuteSql[T](SqlCommand cmd, Func`2 sqlFunc)
at Microsoft.Dynamics.AX.Framework.Database.Tools.SyncEngine.ConfigureSqlDatabaseSettings()
at Microsoft.Dynamics.AX.Framework.Database.Tools.SyncEngine.RunSync()
at Microsoft.Dynamics.AX.Framework.Database.Tools.SyncEngine.Run(String metadataDirectory, String sqlConnectionString, SyncOptions options)
ClientConnectionId:c49c708e-c380-48e9-b81a-b41cca10ad10
##[error]SYNCENGINE(0,0): Error Number: -2,State:0,Class:11
SYNCENGINE : error Number: -2,State:0,Class:11 [C:\DynamicsSDK\Metadata\SyncEngine.proj]
Inner Exception: System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
Database synchronization failed with exit code: -1.
Done Building Project “C:\DynamicsSDK\Metadata\SyncEngine.proj” (default targets) — FAILED.
 

IDX10205: Issuer validation failed for D365 Operations

While setting up a new VM for cutomer project, we came across an issue where we were not able to do the API calls and were receiving following message in the window event logs.

2017-08-09_21-44-48

Clicking “Details” will give you something like below (Trimmed details – showing the relative error message)

IDX10205: Issuer validation failed. Issuer: ‘https://sts.windows.net/GUID-AAD#1/’. Did not match: validationParameters.ValidIssuer: ‘null’ or validationParameters.ValidIssuers: ‘https://XXXXXXXXXX.sandbox.ax.dynamics.com, 00000000-0000-0000-c0000-000000000000, microsoft.erp, https://sts.windows.net/GUID-AAD#2

The first thing to notice that GUIDs are different – these ids should be similar when request is being posted with bearer token. This lead us to check the “UserInfo” table in the onebox machine. However, that didn’t help – so we looked further.

Upon further investigation we found out that web.config file in J:\AosService\WebRoot that had the original domain name related to person who deployed the VM for D365 Operations.

The domain name was different than actual tenant, after making the both same we were able to post the requests through Postman and received successful response. 

The lesson learnt was that we should be deploying the VMs from their tenant’s account instead of partner’s account.

Thanks,

Create Sales Orders through code X++ (AX2012)

Useful code below for creating sales order quickly for testing purposes in scenarios where we have to test bulk sales orders and than do some packing slips and or invoice consolidation…

static void Job_CreateSalesOrderForTesting(Args _args)
{
    SalesId salesId;
    int counter = 0;
    container saleOrdersCon;
    str salesOrders;
    int size = 100;

    void createSalesTable(CustAccount _custAccount)
    {
        SalesTable salesTable;
        NumberSeq NumberSeq;
        NumberSeq = NumberSeq::newGetNum(SalesParameters::numRefSalesId());
        NumberSeq.used();
        salesTable.SalesId = NumberSeq.num();
        salesTable.initValue();
        salesTable.CustAccount = _custAccount;
        salesTable.initFromCustTable();
        salesTable.insert();
        salesId = salesTable.SalesId;
    }

    void createSalesLine(SalesId _salesId, ItemId _itemId, str 50 _inventColorId, str 10 _inventSizeId, str 50 _configId, str 50 _inventLocationId)
    {
        InventDim inventDim;
        SalesLine salesLine;

        select firstOnly inventDim
        where
            inventDim.InventColorId == _inventColorId
            && inventDim.InventSizeId == _inventSizeId
            && inventDim.configId == _configId
            && inventDim.InventLocationId == _inventLocationId;

        if (inventDim){
            salesLine.clear();
            salesLine.SalesId = _salesId;
            salesLine.ItemId = _itemId;
            salesLine.InventDimId = inventDim.inventDimId;
            salesLine.SalesQty = 2; // You can add parameter for this as well
            salesLine.createLine
            (NoYes::Yes, // Validate
            NoYes::Yes, // initFromSalesTable
            NoYes::Yes, // initFromInventTable
            NoYes::Yes, // calcInventQty
            NoYes::Yes, // searchMarkup
            NoYes::Yes); // searchPrice
        }
    }


    for (counter = 0; counter < size; counter++){
        createSalesTable('CUS10580');
        createSalesLine(salesId, '000023000', 'RED', 'L', 'CONFIG', '009');
        createSalesLine(salesId, '000024MMI', 'BLACK', 'M', 'CONFIG', '009');
    }
}

Dynamics AX – Service EndPoints

The following table lists all the service endpoints that were available in Microsoft Dynamics AX 2012 and the new service endpoints that have been introduced in Dynamics AX.

Service endpoint AX 2012 Dynamics AX
Document Services (AXDs) Yes No – Replaced by data entities
SOAP-based Metadata Service Yes No – Replaced by REST metadata
SOAP-based Query Service Yes No – Replaced by OData
OData Query Service Yes No – Replaced by OData
SOAP-based Custom Service Yes Yes
JSON-based Custom Service No Yes (New)
OData Service No Yes (New)
REST Metadata Service No Yes (New)

For full details – please check AX Wiki:

https://ax.help.dynamics.com/en/wiki/dynamics-ax-7-services-technical-concepts-guide/

Dynamics AX (Ax7) Layout

Here is how it looks with RTW (Release to Web) for Dynamics AX

Search

New Dynamics AX Layout - Search Bar

Tiles

The tiles are the main component of the office themed layout where you can put the links to your own workspace and also filter the tiles based on the role assigned to user.

New Dynamics AX Layout - Title

Collapsible Menu

The collapsible menu lists all the Modules, Workspaces and recent browsed pages for quick access. The menu can also be pinned down to make it stick.

New Dynamics AX Layout - Menu

The Layout as a Whole

New Dynamics AX Layout

Hope this gives some technical resources more appetite to look at this new amazing Microsoft’s AX release.

Enjoy !!!

 

Dynamics AX 2012 – Reports – “No data available”

Problem:

A working report suddenly stops working for a “User” in production environment with message “No data available”.

Research:

While report worked for every other user and only that particular user seems to had a problem while running the particular report. While he was able to run other reports in that same module fine.

This was a strange enough situation for us, while we checked code, security etc… at first we were not able to find the exact cause of this behavior. But we were sure it has something to do with the security that is finally applied when running the report. So, we created a test user with same roles assigned on lower environment.

During our debugging and profiling the calls to actual database saw a strange behavior.

The query generated from X++ was same for user who was able to run the report and the user who wasn’t able to run the report, but interestingly the SQL Profiler showed EXTRA parameters added to where clause of SQL that was getting executed. The extra condition caused the data to not appear – the condition was always going to result in a FALSE.

The query generated was something like below notice 1=3

SELECT ………. FROM InventTable T1 Inner Join InventDim T3 … WHERE 1=3

This cause the data to not appear for that user, AX kernel seems to validate the permissions and inject the condition to make sure that data doesn’t come from the source – making the sure that data is being security and row level security is applied though this.

Solution:

The solution to the problem was to add all used tables used in the Query for the report in the user’s privileges in AX.

HTH

CREDIT: #awesome #team #visionet #findingsolutions