Printing reports from code in D365FO

A comment below my blog post Printing reports from code in AX2012 asked me to provide an example for D365FO. Here is it.

The code is virtually identical. Only writing a file to a shared folder doesn’t make a good sense in cloud, therefore I changed the code to return the file to user for download.

SrsReportRunController          controller = new SrsReportRunController();
SysUserLicenseCountRDPContract  rdpContract = new SysUserLicenseCountRDPContract();
SRSPrintDestinationSettings     settings;
 
// Define report and report design to use
controller.parmReportName(ssrsReportStr(SysUserLicenseCountReport, Report));
// Use execution mode appropriate to your situation
controller.parmExecutionMode(SysOperationExecutionMode::Synchronous);
// Suppress report dialog
controller.parmShowDialog(false);
 
// Explicitly provide all required parameters
rdpContract.parmReportStateDate(systemDateGet());
controller.parmReportContract().parmRdpContract(rdpContract);
 
// Change print settings as needed
settings = controller.parmReportContract().parmPrintSettings();
settings.printMediumType(SRSPrintMediumType::File);
settings.fileFormat(SRSReportFileFormat::Excel);
settings.fileName('UserLicenseCount.xlsx');
 
// Execute the report
controller.startOperation();

Dynamics 365 Saturday South Africa

I’m safely back in Prague and I would like to thank everybody who attended Dynamics 365 Saturday in Johannesburg. There were so many of you!

And I want to give special thanks to people who did all the work to make the event happen and those who cared of me there. This was my first visit to South Africa and it was great you showed my lions, local food and everything.

I hope that my talks (about .NET in D365FO and about design for extensibility) gave people some useful information.

Dynamics 365 Saturday isn’t limited to South Africa, of course. There are quite a few already scheduled, therefore check what’s going in your area. It’s all free!

Weird behaviour after moving a form to another package

I recently had to move a form to another package, because we decided to extract some functionality to its own independent package. I moved files, built both packages and everything looked fine, so I started making changes for a new requirement.

But later I noticed something strange in the form. When I opened the form, it didn’t look right. Some new controls (added after the move) were missing and other parts behaved incorrectly (I won’t go into details here). Everything went back to normal when I refreshed the page, but the problem appeared again when I opened the form from menu. Using the refresh button inside the form (beside buttons Open in Microsoft Office and attachments) end up with an error and the application froze.

After making sure that everything is built correctly and restarting everything, I duplicated the form and tried the copy. It worked flawlessly, proving that the form itself was implemented correctly. Therefore, I suspected that the environment somehow used a cached design of the form as it was defined in the old package. Building the packages with and without Build Pre-Compiled Form didn’t make any difference, so I tried one more thing.

I searched the packages directory for the name of my form and I did find something suspicious. There was a file in WebContent subfolder of the original package:

[…]\PackagesLocalDirectory\MyOriginalPackage\WebContent\Forms\myform.json

Just deleting the file didn’t fix the problem, but restarting the server after that did. It would be likely sufficient to restart IIS; I turned the whole machine off because I went home and tried the result the next day.

I wanted to write this down because others might run into the same problem. And it looks like a bug in Microsoft tools, therefore they should look at it and fix it.

XML response from OData services

If you call OData services in AX 7 (Dynamics 365 for Finance and Operations), you typically get data in JSON format, like this:

{
  "@odata.context":"https://myaxinstance.cloudax.dynamics.com/data/$metadata","value":[
    {
      "name":"ElectronicPaymentTypes","kind":"EntitySet","url":"ElectronicPaymentTypes"
    },{
      "name":"ExpensePaymentDetails","kind":"EntitySet","url":"ExpensePaymentDetails"
    }
    ...
  ]
}

JSON is a simple, lightweight format with good support in many tools, but sometimes you would rather get XML. XML is by no mean deprecated – it’s more than a format; you get a whole platform with capabilities useful for validations (XML schema), querying (XPath, XQuery), transformations (XSLT) and so on. Or you simply have a component that accepts only XML and not JSON.

Fortunately OData services aren’t limited to JSON; they can return XML as well. Simply add HTTP header Accept with value application/atom+xml,application/atomsvc+xml,application/xml and you’ll start getting the same data in XML format:

<ODataServiceDocument xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://schemas.datacontract.org/2004/07/Microsoft.OData.Core">
  <EntitySets>
    <ODataEntitySetInfo>
      <Name>ElectronicPaymentTypes</Name>
      <Title i:nil="true" />
      <Url>ElectronicPaymentTypes</Url>
    </ODataEntitySetInfo>
    <ODataEntitySetInfo>
      <Name>ExpensePaymentDetails</Name>
      <Title i:nil="true" />
      <Url>ExpensePaymentDetails</Url>
    </ODataEntitySetInfo><ODataEntitySetInfo>
  ...
  </EntitySets>
</ODataServiceDocument>

If you use Postman, for example, this is where you can put the header:

Of course, that you get XML format doesn’t mean that you get the structure you want. You still may need to transform it to something more suitable for your purposes.

The problem is that seems to be respected only at the highest level, i.e. the list of available services. The individual services return JSON regardless of the header.

‘Get latest’ failed on a file without permissions

A few days ago I was getting latest changes from VSTS to an AX 7 development box when it failed on a certain (custom) .dll file, because Visual Studio wasn’t able to overwrite the file.

I made sure that all AX services are down, but it made no difference. Then I looked at file permissions and found that I didn’t have any permissions at all, which was really weird. I did use the environment a few weeks ago without problems.

Ultimately I restarted the server and the file disappeared, therefore I was able to get the new version from VSTS without issues. It seems that the file was technically already deleted and I just saw some strange state of the system.

If I see something similar next time, restarting the machine will be one of my first steps.