OfflineAuthenticationAdminEmail overwritten

My F&O environment asked me to log in every time to when I started debugging. I changed OfflineAuthenticationAdminEmail in DynamicsDevConfig.xml (at %USERPROFILE%\Documents\Visual Studio Dynamics 365), but I noticed that the value got overwritten every time when I started Visual Studio and opened an F&O project.

I tried changing the value in j:\AosService\PackagesLocalDirectory\bin\DynamicsDevConfig.xml, but it didn’t have any effect.

After some searching, I found that the value is copied from Provisioning.AdminPrincipalName in web.config (e.g. j:\AosService\WebRoot\web.config). Setting my account name there finally fixed the problem.

Entity collection as OData action parameter

Data entities in F&O can be exposed through OData protocol. You can also add OData actions by creating methods in X++ and decorating them with SysODataCollectionAttribute.

You can see an example in MssLeaveRequestDateEntity.getDirects():

[
    SysODataActionAttribute('getDirects', false),
    SysODataCollectionAttribute('return', Types::Record, 'MssLeaveRequestDateEntity')
]
public static List getDirects(
    str reportingPersonnelNumber,
    date fromDate,
    date toDate,
    LeaveRequestApprovalStatus leaveRequestStatus)
{
    List list = new List(Types::Record);
    ...
    return list;
}

It has parameters of several types and it returns a collection of entity records (additional metadata is provided in SysODataActionAttribute).

Now what if you want to add such a collection as an input parameter? It sounds straightforward, but if you do it, the action will completely disappear from the entity because it fails to generate.

I was able to get a confirmation that such a parameter type isn’t supported. It’s another case when event logs helped me. Namely, I found a warning in Application and Services Logs > Microsoft > Dynamics > AX-ODataService > Operational log. At the General tab, it said merely OData Metadata Build Warning, but the Details tab revealed much more:

ComponentNameODataServiceMetadataBuilder
infoMessageAction myTest (Method = myTest) on Entity MyEntity has a parameter (Type = Microsoft.Dynamics.Ax.Xpp.List, Name = inRecords) that resolves to an EntityType collection, which is not currently supported. Remove the parameter.

All right, so it’s explicitly unsupported. Note that this is just about a collection of records; you can use collections of primitive types such as numbers and strings.

The fact that this kind of warning can be found in event logs may be the most important information in this blog post. It may help with debugging of other issues related to OData in F&O.

Happy New Year 2024

Happy New Year! (To everyone who follows Gregorian calendar :)).

Let me look a bit at what I did in 2023 and what I expect in 2024.

I keep working for a large end-user company. I do a lot of different things there (X++, Azure Functions, code reviews, Powershell, DevOps processes and so on), but a lot of that is focused on the single company and it’s not to be shared with the community.

A new Dynamics community site was launched. It’s developed in a different way, which should make its development more agile. On the other hand, there are still quite a few bugs and missing features and their resolution has been slow so far. But progress is being made, so hopefully we’ll have a much better site at the end of 2024.

This year, unified development experience for F&O will become generally available. I still haven’t got chance to play with it too much, which is a pity. I’m keen to, hopefully it’ll change soon. Also, changes in storage pricing are expected in near future, which is an important topic for the new development/admin experience.

We can expect more and more convergence and integration of F&O and Power Platform. I made just a few Power Apps and flows in 2023, let’s see if there will be more in 2024.

In March, I’m going to attend Microsoft MVP Summit in Redmond. It’s a conference for MVPs and Microsoft employees, where MVPs have a chance to meet each other and Microsoft product teams, learn about upcoming features, provide feedback and so on. The social part is important; there are people that I’d have never met in person if I didn’t attend MVP Summits. There were no summits in the era of Covid and I skipped it last year, therefore it’ll be my first summit since 2019.

In May, I’m going to DynamicsMinds conference in Slovenia. I gave a few talks there last year and it was a great event, so I’m happy to come again. I hope to see some familiar faces there!

Query/QueryRun with temporary tables (AX/F&O)

I noticed that some developers believe that Query* classes can’t be used to query temporary tables. It is possible; it just requires an extra step that isn’t needed with regular tables.

When working with temporary tables, each buffer (variable) of the same table can refer to a different set of temporary data. Therefore using the right buffer (reference to a particular data set) is crucial. This is true for select statements in code, form data sources, and for Query* classes as well.

If you want to query temporary tables with Query* classes, you’ll define a query (with classes like Query and QueryBuildDataSource) in exactly the same way as with regular tables. The place where you must pass references to temporary data sets is an instance of QueryRun class, namely setCursor() (or setRecord()) method.

If the query uses several temporary tables, simply call setCursor() several times – the system will find the data source for the given table. The method also has an extra parameter (_occurrence) for the case when you have multiple data sources for the same table.

Here is a complete example using standard tables, therefore anyone can simply copy and run it. It shows all steps – inserting data to temporary tables, creating a query, passing temporary tables to a QueryRun object, running the query and showing returned records. It uses F&O syntax, but the overall approach is the same in Dynamics AX too.

TmpTableName name;
 
name.RefTableId = 1;
name.TableName = 'TableA';
name.insert();
 
TmpTableIdMap map;
map.MainTableId = 1;
map.MainFieldId = 42;
map.insert();
 
Query query = new Query();
QueryBuildDataSource nameDs = query.addDataSource(tableNum(TmpTableName));
 
QueryBuildDataSource mapDs = nameDs.addDataSource(tableNum(TmpTableIdMap));
mapDs.addLink(fieldNum(TmpTableName, RefTableId), fieldNum(TmpTableIdMap, MainTableId));
 
QueryRun qr = new QueryRun(query);
qr.setCursor(name);
qr.setCursor(map);
 
while (qr.next())
{
    TmpTableName nameFetched = qr.get(tableNum(TmpTableName));
    TmpTableIdMap mapFetched = qr.get(tableNum(TmpTableIdMap));
 
    info(strFmt('%1 - %2', nameFetched.TableName, mapFetched.MainFieldId));
}

Public preview of the new F&O dev experience

Something that was talked about for a long time is getting closer to reality. F&O development will no longer require those huge VMs with SQL Server and everything. Instead, you’ll just install some VS extensions, connect to Dataverse, download F&O code and metadata and start developing. The runtime (web server, database) will be in cloud, which means that running and debugging your changes requires deploying them to an F&O environment in cloud.

Microsoft calls it a unified experience because it’s going in the direction used by other Dynamics products, it utilizes Power Platform and it provides tighter and easier integration between F&O and Power Platform.

Here is a brief introduction by Peter Villadsen: The Public Preview for the Unified Experience is live!. It contains links to the documentation with more details (which is also in preview).

I’m looking forward to the extra flexibility provided by the new solution. It should also have a positive impact on costs, because development teams won’t need so many powerful VMs (although details also also depends on things like Dataverse pricing). My recommendation is trying it and getting familiar with the new approach, but not hurrying with the real adoption, because changes are expected before it becomes generally available.