Pages

Saturday, May 27, 2017

First book about Dynamics 365 for Operations development is out

From the publishers homepage:

"Dynamics 365 for Operations is the ERP element of Microsoft’s new Dynamics 365 Enterprise Edition. Operations delivers the infrastructure to allow businesses to achieve growth and make better decisions using scalable and contemporary ERP system tools.

This book provides a collection of “recipes” to instruct you on how to create—and extend—a real-world solution using Operations. All key aspects of the new release are covered, and insights into the development language, structure, and tools are discussed in detail.

New concepts and patterns that are pivotal to elegant solution designs are introduced and explained, and readers will learn how to extend various aspects of the system to enhance both the usability and capabilities of Operations. Together, this gives the reader important context regarding the new concepts and the confidence to reuse in their own solution designs.

This “cookbook” provides the ingredients and methods needed to maximize the efficiency of your business management using the latest in ERP software—Dynamics 365 for Operations."

Buy it from the publisher or from Amazon.

Friday, May 19, 2017

Use tags to find related bits and pieces in your code base

A lot of elements, if not all, in Dynamics 365 for Operations (D365FO) has a property called "Tags".

With this property you can link all sorts of different otherwise unrelated elements. You could for example use this as part of a bigger change you need to do to your code base, marking all the bits you need to modify.

Adding a tag is as simple as just using it:


For Visual Studio to find places where the tag is used, you need to do a  build with the "Build cross reference data" option checked:


And here is where you search for tags:




And here is the result:


This ought to work for code to. The editor knows about the tags and has intellisense for them:


But the "Find tag references" tool doesn't pick them up. I wonder if that is a bug or not.

And in my opinion you should try to not go overboard tagging away all day long.

Monday, May 15, 2017

FormRun.wait, Box and ChangeCompany - a poor cocktail

I have had some code like this (simplified for the purpose of the example):
...
changeCompany('xyz')
{
    formRun = new FormRun(...);
    formRun.wait();
}

Box::YesNo(...)
If you run this code and manually change company while the form is open and "waiting", the call to Box will make the system freeze up. I have reported this as a bug, but it is not accepted to be fixed.

The workaround, or you could argue proper solution, is to add an event handler for formRun.lifecycleHelper().StageChanging and run the Box code when the stage of the form changes to "Closing". That way Box is called before the form is entirely closed and the company account is changed, and then Box runs all right.

Friday, April 7, 2017

Use Microsoft Flow to start up your Azure VMs

Having Azure VM's running when no one uses them is the cloud equivalent of setting your money on fire.

With the ARM deployments we can do for D365fO now, we can pretty easily make the machines shut down automatically based on a schedule:


But how about startup? If you start a machine manually it takes a while before you can connect to it and use it. So it is preferred to start machines before the workday starts. 

If you control startup with scheduled RunBook scripts you risk starting machines that will not be used during the day. Developers might be on other projects, being sick or being on vacation.

So I have been looking into using Microsoft Flow to start machines. The idea is that a developer opens his/her Flow app before leaving their home in the morning, to start the machines they want to work on that day. Here is how that could look in the Flow app:

    
To get there, first step is to create an Azure Automation account and create the RunBook for starting a VM. You can find the RunBook as a template in the Azure Portal. The process is very well described in this article on the Axology blog: https://axology.wordpress.com/2016/12/09/automated-startup-and-shutdown-of-azure-vms/

The Flow app is very simple to setup. Here are the steps for creating the app button (sorry, some of this is in danish).

First add the manual trigger:


Then add the action, which in this case is an "Azure Automation - Create job" action:



Finally I get a notification when the job is done. Not when the machine actually runs, but when the job kicking off the startup is done:


That is it for a really simple flow. You can probably think of a lot of bells and whistles to add.

I would like to try it out with one of the physical buttons that works with Flow, like Flic, as the trigger:


A button is ordered...

Language issue in AX 2012 with Views built on security tables

Some of the security related system/kernel tables in AX 2012, like for example SecurityRole, is backed by Views in the model store.

If you look at the Views in the model store you can see that some fields hold a label id rather than a text. For SecurityRole, the fields Name and Description holds label ids.

Somewhere in the AX kernel these label ids are converted to actual texts according to the language of the user. So inside AX we don't see these labels, but we see the language specific texts.

This is also the case if you create a View where these tables are part of the meta data.

However if you change the language for your user, it doesn't seem like these Views are updated according to the new language. They keep returning data in the previous language, even after restarting the client and AOS. The only way I have found to make it use the new language is to manually synchronize the view from the AOT.

Thursday, April 6, 2017

Resolve dll references for a project generated from a template

When you create a new project from a template, for example a new Best Practice Rules project, you might get a bunch of references that aren't resolved:



To resolve these you can individually point each reference to the correct dll, or you can take the following faster approach.

In Solution Explorer, right-click your project node and click Properties. The Project Designer appears:

Select the Reference Paths page. In the Folder field, type the path of the folder that contains the items you want to reference, and then click the Add Folder button:

The path for most D365fO dll's is J:\AosService\PackagesLocalDirectory\Bin\

Click Save to save the setting and then close the dialog:


And ... voilĂ :

Monday, April 3, 2017

A gentle introduction to the Immediate Window

Ivan Kashperuk wrote a blog post a while ago about using the Immediate Window when debugging. I wanted to do a more gentle introduction to it, hopefully making you want to go read Ivan's much more thorough post.

The Immediate Window is one of the windows that are open while you debug. The idea is that you can get it to perform simple X++ expressions, using the variables of the program you are debugging.

Now in Dynamics 365 for Operations a thing like tables ids or class ids is not something you can see in the AOT, so debugging a piece of code using these id's can be difficult. You don't know which tables or class names the id's correspond to. This is where I for now use the Immediate Window most, calling something like this (where _tableId is a variable in my program):



There are some technicalities you have to bear in mind when using this. You have to use .NET syntax and .NET types for the expression, it is case sensitive and it is not able to deal with all statements from X++ (like for example a select statement).

You can to some extend use the same expressions from the Immediate Window as conditional breakpoinst. There are some caveats though. If you call stuff from the AOS kernel, some pieces of the kernel are still written in unmanaged code and they will fail with different kinds of errors. Only the parts of the kernel written in managed code will work.  

If you don't follow Ivan's blog already, you should. It is one the of best blogs for developer related information. You can find it at this URL: http://kashperuk.blogspot.com

Thursday, February 16, 2017

AXBUILD fails with a "System.IO.IOException: The file exists" error

Here is a problem with AXBUILD that today added more grayness to my limited amount of hair:


The reason: When AXBUILD kicks off the compilation-threads it needs some temporary files and it uses a .NET function to get the names. It turns out that if the user this runs as, has more that 65535 files named as tmpXXXX.tmp in the Temp folder, the function can simply fail. The naming apparently runs from tmp0000.tmp to tmpFFFF.tmp. 

So the solution was to clean up this folder for our build user, and now all our builds are running again.

Friday, January 6, 2017

Authoring Best Practice checks that use XML based input

In AX7 you can pretty easily write and deploy your own Best Practice checks. The process of doing so is described in this article on the wiki.

Some of the standard Best Practice checks use XML files as input. These XML files are found under your local packages folder, in ..\PackagesLocalDirectory\Bin\BPExtensions\RuleXml

The following is an example of how you can write your own Best Practice check that uses an XML file as input. The check itself is used to check the naming of table extensions. We want to check that a certain prefix is part of the name, and that it is put in the correct place in the overall name. The prefix to look for is specified in the XML file.

The XML file looks like this:
The file is stored in ..\PackagesLocalDirectory\Bin\BPExtensions\RuleXml and the name is MVPProductPrefix.xml. The name is important, as a reference is made to it from the code.


Your Best Practice class needs to extend either DetectorWithXMLDataFile or MetadataDetectorWithXMLDataFile depending on the type of your check. In this case we extend MetadataDetectorWithXMLDataFile since we will be looking at table extension names.

Included in your solution you need to add a data contract class for the XML file. This class must extend from RulePatternsBase.
The framework and the base classes will then do the rest of the work with loading the XML file, de-serialize it and caching it.

Here is the code:

And here is the code for the diagnostic item:

I'd like to thank Joris de Gruyter for helpful hints on how to solve this. And .NET Reflector has been a great tool to look into the standard Best Practice dll's to figure out how they work (Microsoft MVPs get a free license for .NET Reflector from Redgate).