‘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.

Recurring Integrations Scheduler: File already exists

I’ve recently run into a problem with Recurring Integrations Scheduler and I think I won’t be the only one, therefore I’m going to explain it here.

The Recurring Integrations Scheduler (RIS) supports both the old recurring integrations API (enqueue/dequeue) and the new package API, which is the recommended approach. With the package API, you can either import whole packages (which you must prepare by yourself in some way) or you can give RIS actual data files (XML, CSV…) and let it build packages for you. That’s the scenario I’m talking about below.

If you want RIS to create packages, you must give it a package template. Go to the Data Management workspace in AX 7, create an import job, configure it as you like and then download the package. I’m using the Customer groups entity as an example.

You’ll get a file with a GUID as the name, such as {99DD43E4-936E-4402-80E6-1477013A5275}.zip. Feel free to rename it; I’ll call it CustGroupImportTemplate.zip.

This is its content:

You can see one data file for the entity (Customer groups.xml in my case) plus some metadata defining the import project.

It’s not exactly what’s needed, as we’ll see later, but let’s continue for now with this package.

Go to RIS and configure an import job. Don’t forget to set Package template to the package file.

Make sure the job is running, create an input file in the right format and put it into the input folder.

Unfortunately the import fails and you’ll find these files in the Processing errors folder:

The status file merely says that StatusCode = BadRequest and events logs for RIS (Applications and Services Logs > Recurring Integrations Scheduler) don’t reveal anything else either. More useful event logs are under Applications and Services Logs > Microsoft > Dynamics > AX-OData Service, where you can find something like this:

System.InvalidOperationException: Exception occurred while executing action ImportFromPackage on Entity DataManagementDefinitionGroup: The file ‘C:\windows\TEMP\005DE7CC-C7E8-410D-8690-7A63C30224BF_FF5EE0BE-205C-48BC-8987-96C007CE74ED\Customer groups.xml’ already exists.

A unique folder name is generated for each import, therefore the problem isn’t related to existing files in the Temp folder.

To make it short, the problem is in the package file itself, which you unfortunately never see, because it’s automatically deleted on failure. If you captured it and looked inside, you would find this:

There are literally two files with the same name and therefore the attempt to unpack the archive fails on the second instance.

How does this happen?

One file is coming from the package template. The other is the input file, which RIS renamed to match the entity name and added to the archive. Having files with same names is supported by ZIP, but the library used by RIS for unpacking isn’t able to handle it.

To get it working correctly, you must remove the data file (Customer groups.xml) from the package used as a template. A better solution, though, would be modifying RIS to replace the file instead of attaching another file with the same name.

Recurring Integrations Scheduler

You may have heard about QuartzAX, an application for file-based integration with AX 7 (Dynamics 365 for Finance and Operations, Enterprise Edition). Microsoft announced at the last Technical conference that it would be released in a few days, but it didn’t happen and it looked like it wouldn’t ever be made available. But it has changed today.

You can find its source code and documentation on GitHub under the new name: Recurring Integrations Scheduler.

Open API for JSON-based custom services in AX 7

If you’re familiar with SOAP web services, you likely know that they use Web Services Description Language (WSDL) to document what operations a service provide, what parameters they accept, what they return and so on. This information can be used to generate proxy classes, which you can use to communicate with remote systems simply by calling class methods and all implementation details are handled for you under the hood.

While SOAP-based services offer many configuration options (e.g. you can switch from TCP to HTTP just by changing a config) and great tooling, sometimes it’s beneficial to use a less sophisticated approach and expose and call services directly over HTTP (that’s why AX 7 added JSON-based endpoints for custom services). Almost everything can communicate over HTTP, it doesn’t require any extra libraries, it’s very flexible and so on. There are some patterns how to design such services (especially REST), but you can do whatever you want. But it means that you have to give up features like code generation of proxy classes. Or not?

While HTTP web services don’t have to use any descriptions similar to WSDL, it doesn’t mean they can’t. One of your options is Open API (also known as Swagger), which allows you to describe services in JSON or YAML. There are many tools for working with these descriptions, such as an editor, code generators for many languages, a generator of documentation, you can generate Open API descriptions for your WebAPI projects, there is a support for Open API in Azure Logic Apps, in Azure API Management and so on.

Let me show you an example of such a description for a custom service in AX 7 (Dynamics 365 for Finance and Operations, Enterprise Edition). You don’t have to examine it in detail, just notice that it describes available operations, what URL you must use to reach it, what parameters it expects, what it returns and so on, and it also contains additional textual annotations.

  "swagger": "2.0",
  "info": {
    "title": "User management",
    "description": "Services for user management offered by Microsoft Dynamics 365 for Finance and Operations, Enterprise Edition.",
    "version": "1.0.0"
  "host": "YourAX7Instance.cloudax.dynamics.com",
  "basePath": "/api/services",
  "schemes": [
  "paths": {
    "/SysSecurityServices/SysUserManagement/getRolesForUser": {
      "post": {
        "summary": "Gets security roles",
        "description": "Returns security roles currently assigned to the given user in Microsoft Dynamics 365 for Finance and Operations, Enterprise Edition.",
        "operationId": "getRolesForUser",
        "produces": [
        "parameters": [
            "name": "body",
            "in": "body",
            "description": "User ID as defined in UserInfo table.",
            "required": true,
            "schema": {
              "$ref": "#/definitions/GetRolesRequest"
        "responses": {
          "200": {
            "description": "Roles assigned to user",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              "example": [
          "500": {
            "description": "Processing inside Dynamics 365 for Finance and Operations failed."
  "definitions": {
    "GetRolesRequest": {
      "type": "object",
      "required": [
      "properties": {
        "axUserId": {
          "type": "string",
          "example": "admin"

The first thing we can do with it is to show the same information in a more readable way. Open the online editor and paste the sample code there. On the right side, you’ll see it rendered as a nice HTML document:

Service documentation generated by editor.swagger.io

The editor can also use YAML (and will offer you to convert JSON to YAML), which is a more succinct format, therefore you may prefer it for manually edits. I intentionally used JSON, because we’ll need it in the next step.

Code generation

Now let’s generate code for calling the service, so we don’t have to do it all by hand and deal with all implementation details of communication over HTTP, with (de)serialization of values and so on.

Before you start, download and configure AX service samples from GitHub and verify that they work. Then create a new console application in ServiceSamples solution, where we’ll call a custom service through generated client classes. My code below assumes that the project is called JsonConsoleWithSwagger; you’ll have to adjust a few things if you use a different name.

Client classes can be generated by several different tools, therefore the following process is just an example; feel free to use other options in your projects.

Download and install NSwagStudio (if you use Chocolatey, as I do, all you need is cinst nswagstudio). Run NSwagStudio, paste the JSON on Swagger Specification tab, tick CSharp Client and change a few properties at CSharp Client tab:

  • Namespace: JsonConsoleWithSwagger (or something else, if you named the project in Visual Studio differently)
  • Class Name: UserManagementClient
  • Use and expose the base URL: No
  • Class style: Poco

You could use different parameters, such as different Class style, but this will suffice in our case.

Then press Generate Outputs, which will generate corresponding C# code. Copy it to clipboard, create a new class in your Visual Studio project and replace the file content with the generated code.

We need to add just two things – the actual URL of your AX instance and an authentication header. We don’t want to change the generated code itself, because we may need to regenerate it later and we would lose our changes. Fortunately, it’s not needed – the class is partial, therefore we can create another part of the same class in a separate file and keep generated code and custom code cleanly separated.

Create a new file in your project and paste the following code there:

using AuthenticationUtility;
using System.Text;
using System.Net.Http;
namespace JsonConsoleWithSwagger
    public partial class UserManagementClient
        partial void PrepareRequest(HttpClient client, HttpRequestMessage request, StringBuilder urlBuilder)
            client.DefaultRequestHeaders.Add(OAuthHelper.OAuthHeader, OAuthHelper.GetAuthenticationHeader());
        private void PrependAxInstanceUrl(StringBuilder urlBuilder)
            string service = urlBuilder.ToString();

PrependAxInstanceUrl() takes the address of your AX from configuration and puts it at the beginning of the request URL.

Then the code sets the authentication header with the help of OAuthHelper from AuthenticationUtility project, therefore we must add a reference to it:

The last step is adding code to Main() method of Program class to actually call the service. We create a request object (please provide an existing user ID there), create an instance of the UserManagementClient class generated from our Open API document and call the operation. It’s asynchronous, as recommended, but we don’t really need that here, therefore the code immediately asks for the result and waits for it. Then we iterate roles received from AX and puts them into console.

GetRolesRequest request = new GetRolesRequest()
    AxUserId = "user7281"
var roles = new UserManagementClient().GetRolesForUserAsync(request).Result;
foreach (string role in roles)

That was easy – we didn’t have to bother about what exact parameters the services expects (and we would get a compile error if we did it wrong), we didn’t have to serialize objects to JSON or anything like that. The generator was able to create all the code for us, it just needed to know how the service looks like.

In this case, I wrote the Open API document by hand, which obviously took some time. A much better approach would be generating it from metadata of custom services in AX, and while I don’t have such a solution in the moment, it’s definitely doable. Some information is already in place (e.g. getting the list of operation is easy), services and service groups already have properties for description (although they’re currently empty in most cases) and things like parameter description can be included in XML documentation. It still doesn’t cover everything, but additional information can be easily provided in attributes. It’s exactly what Swashbuckle does, e.g. with SwaggerResponseAttribute and RequiredAttribute.

I think it’s something that Microsoft should use for its custom services, to provide documentation and to make custom services much easier to consume. Open API / Swagger is a natural choice for this purpose, because Microsoft is a founding member of Open API Initiative and already support it in several products. Maybe Microsoft could somehow utilize Swashbuckle inside the implementation of custom services, instead of building something new from scratch.

But even if Microsoft isn’t interested, I believe it would still be useful for many people, therefore the community could build a tool to extract information about custom services and generate Open API documents. It wouldn’t necessarily have to support all features (or not from the beginning); people can easily add textual annotations, examples and so on in Swagger Editor, if needed. But being able to automatically generate JSON-based client classes for any custom service would be really handy.

Discovery of JSON-based custom services in AX 7

If you download AX integration samples from GitHub, you’ll see (in JsonConsoleApplication project) that you can call JSON-based custom services by code like this:

var request = HttpWebRequest.Create(ClientConfiguration.Default.UriString + "api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo");
request.Headers[OAuthHelper.OAuthHeader] = OAuthHelper.GetAuthenticationHeader();
request.Method = "POST";

It will call the operation and return its return value as JSON:

    "CurrencyInfo": {
        "Description":"US Dollar",

This is what happens when you use the POST method of HTTP; if you switch to GET, you’ll actually get some information about the service.

Therefore if you merely change the value of request.Method:

var request = HttpWebRequest.Create(ClientConfiguration.Default.UriString + "api/services/UserSessionService/AifUserSessionService/GetUserSessionInfo");
request.Headers[OAuthHelper.OAuthHeader] = OAuthHelper.GetAuthenticationHeader();
request.Method = "GET";

you’ll get a very different response:

    "Return": {

You can see that the operation doesn’t expect any parameters and it returns a single object of AifUserSessionInfo type. This gives you some limited information about how to use this service.

You can also use GET requests to discover existing services and their operations.

/api/services gives you a list of all service groups:


/api/services/UserSessionService provides a list of services in the service group:


/api/services/UserSessionService/AifUserSessionService shows all operations of the individual service:

    "Operations": [

Don’t forget than opening an URL in browser makes a GET request, therefore you don’t have to write any code to get this kind of information about custom services.

But maybe you would like something a bit more sophisticated, which is the topic of the next post: Open API for JSON-based custom services in AX 7.