In this chapter, we will cover the following recipes:
- Creating the Visual Studio Team Services project
- Connecting Visual Studio to your Visual Studio Team Services
- Creating a new Model and Package
- Configuring project and build options
- Creating a Label file
Microsoft Dynamics AX 2012 underwent a name change in what would have been version 7. The official name is now Microsoft Dynamics 365 for Operations. It isn't just that the version number has been dropped, but it appears to have been adopted into the Microsoft Dynamics 365 product suite. The product is not a component of Microsoft Dynamics 365, which is just a way to group Microsoft's various business solutions. We can't, therefore, shorten the name to Dynamics 365, we will refer the product by either its full name or the abbreviation Operations.
New features will be introduced to Operations as both a continual and cumulative process. There are two main types of update, Platform and Application. Platform updates are similar to the binary updates in prior releases, but also contain AOT elements that are now locked and can no longer be changed. Platform updates can contain changes to the language, and new features have been brought in with each bi-yearly release. When running in the Cloud, Microsoft will periodically release updates to the Platform for you. This is needed, since the it uses Azure SQL Server and they may need to service the platform in order to maintain compatibility to the database server.
Application updates are changes to the other packages that make up the source code of Operations, and can be considered similar to the meta data updates in previous releases of Operations.
This book was started on the May 2016, or Update 1 release and has been updated with each release. The version on publication is Update 5, released in March 2017.
All development work is carried out in conjunction with Visual Studio Team Services or VSTS. It used to be optional, but the implementation process that is managed through Lifecycle Services (LCS) requires that we have a VSTS project linked to it to function to its fullest. This is not just for source control and work management, but it is also used when performing code upgrades.
Please see the following links for further reading on Microsoft Dynamics 365 for Operations:
- For more information on LCS, please see the link, https://lcs.dynamics.com/Logon/Index
- An overview of Microsoft Dynamics 365 for Operations for Developers and IT Pros is available at https://docs.microsoft.com/en-us/dynamics365/operations/dev-itpro/
- To obtain an evaluation copy of Microsoft Dynamics 365 for Operations, please see the link, https://docs.microsoft.com/en-us/dynamics365/operations/dev-itpro/dev-tools/get-evaluation-copy
All development work in Operations is either performed on a development virtual machine hosted in Azure, or a local virtual machine. Each developer will use their own virtual machine. Azure hosted virtual machines are deployed through LCS under your own Azure subscription, and can be used to development, learning, and demonstration. Once, as a customer, a cloud hosted subscription has been bought, you are provided 3 environments as part of that subscription under Microsoft's subscription. These are Build, Sandbox, and Production. The build sever is a OneBox server (all in one virtual machine) that is also labelled Development, but it should always be used as a build server and not for development. The sandbox server is a full environment, with multiple servers using a separate Azure SQL Server. The production environment is the environment that you (as a customer) will go live with. All code must first be deployed to the sandbox before it is applied to live, which this is enforced by LCS - no more 'quick fixes' directly into live, and no access to SQL server for the production environment.
The on premise version of Operations may allow us to bypass some of these rules, but we shouldn't try - these practices of forcing code through a full testing cycle are very important. Waiting a couple of days for a needed feature may be inconvenient, but regression is perceived very negatively by users. During the implementation we ask a lot of the users, they are already busy with their jobs and are being asked to also help with testing new software, so user buy-in to the project is a critical factor, and regression is the most efficient way of eroding the initial excitement of delivering new software.
For local development virtual machines that are often the cheapest option, we will download the virtual machine from Microsoft Connect. This is a website used for many programs at Microsoft, and access is provided to partners and customers.
The terms Visual Studio Team Services and Team Foundation Server (TFS) are often used interchangeably. In Visual Studio, the user interface states that we are connecting to a Team Foundation Server. However, we are actually connecting to VSTS, which is an online service. VSTS is required for Operations development, and that is what we will use.
The project is normally created under the end-user's VSTS site, unless the work is being written as an ISV solution (or a personal development or learning project). The reason for using the client's VSTS system is that LCS is associated with the VSTS site, and support calls created through Cloud-powered support are generated within the associated VSTS. Cloud powered support is an online support solution within LCS that is exposed to the Operations client, allowing users to log support issues with their internal support team.
For up to five users, VSTS is free, and the customer can create many accounts with limited access without charge. These accounts as called stakeholder accounts, and allows the user access to work items, which also allows the users the ability to log support calls from within Operations. For those with an MSDN subscription, the five user limit is not counted.
This process is normally performed as part of the LCS project creation. If this were an implementation project type, the project is created when the customer signs up for Operations. The customer would then invite their Cloud solution provider (Partner) to the project. If this were an internal development project, such as a new vertical solution by an ISV, a Migrate, create solutions, and learn Dynamics 365 for Operations project type would be used.
In either case, we will have an LCS project, which will usually have an Azure VM deployed that acts as a build server.
For simplicity, and to keep the focus on software development, a project of type Migrate, create solutions, and learn Dynamics 365 for Operations was created for the purpose of the example of the book.
Before we get started, we will need an LCS project and a VSTS site. The VSTS site can be created through the following link:
Once we have the site created, we can then create our project.
To create the project, follow these steps:
- Navigate to your VSTS site, for example, https://<yourdomain>.visualstudio.com/.
- Under Recent projects & teams, click on New.
- Complete the form as shown as follows:
Unique name, careful to name the projects for easy recognition, and how they are ordered. This is more important for ISVs who may have many projects.
Short description of the project
Team Foundation Version Control
- Press Create project.
- Once complete, you can then navigate to your project and work with VSTS in order to plan your project.
- To authenticate with LCS, we will need to generate a personal access token; to set this up, click on the control panel (cog) icon, as shown in the following screenshot:
- This takes you to the control panel, again, on the top-right click on your name and choose Security, as shown in the following screenshot:
- The personal access tokens option is selected by default; on the right-hand pane, click on Add.
- On Create a personal access token form, enter a short description, for example, the LCS project name. Set the Expires in field based on how long you would like it to last for.
- Leaving the Accounts and Authorized scopes fields as default; press Create token.
- Finally, copy the resultant access code into a safe place; we will need it when we link VSTS to LCS. If we don't, we will have to create a new access token as you can't see it after the web page is closed.
Next, we will need to link the project to our LCS project. If an LCS project is not currently linked to a VSTS project, we get the following message on the left hand side, as shown in the following screenshot:
To configure VSTS for the LCS project, follow these steps:
- To authenticate with LCS, we will need to generate a personal access token, so from within VSTS.
- Click on the Setup Visual Studio Team Services button in the Action center dialog box.
- On the Enter the Visual Studio Team Service site page, enter the URL of our VSTS site into the Visual Studio Team Services site URL field; for example, https://<mysite>.visualstudio.com/.
- Enter the personal access token generated earlier into the Personal access token field.
- Press Continue.
- On the Select the Visual Studio Team Service project page, select the project from the Visual Studio Team Service list.
- You are then shown the Workitem type mapping list. This allows you to select how to LCS Workitem Type / LCS Workitem Sub Type elements to VSTS Workitem Type elements. Leave this as the default and press Continue.
- On the final Review and save page, press Save.
- This takes us back to the main project page and the action center will ask you to authorize the project; click on Authorize.
- You will be warned about being redirected to an external site; click on Yes.
- You may be asked to log on; if so, do it with the account you use for VSTS, which might be your Microsoft account.
- This will open the Authorize application page from within VSTS, and you will be told that you are allowing Microsoft Dynamics Lifecycle Services to access the VSTS and the specific permissions it will receive. Press Accept.
Operations uses VSTS for its source control, work, and build management. The only steps here that we technically must perform are step 1 through step 5, but without performing the previous steps, we lose the ability to integrate LCS. If our project was for a customer implementation, we should consider it mandatory to integrate VSTS with LCS.
For more information on VSTS and LCS, please check out the following links:
- AX Dev ALM usage guide and resources (https://blogs.msdn.microsoft.com/axdevalm/)
- LCS for Microsoft Dynamics 365 for Operations customers (https://ax.help.dynamics.com/en/wiki/how-lifecycle-services-for-microsoft-dynamics-ax-works-lcs/)
- Developer topology deployment with continuous build and test automation (https://ax.help.dynamics.com/en/wiki/developer-topology-deployment-with-continuous-build-and-test-automation/)
The next link is useful background knowledge, but a lot of this is one for you when using an implementation LCS project:
- Set up technical support for Microsoft Dynamics 365 for Operations (https://ax.help.dynamics.com/en/wiki/ax-support-experience/)
This link is for when we have a customer implementation project and demonstrate some of the synergy of leveraging VSTS and LCS with Operations.
Each developer has their own development VM, hosted either in Azure or locally. This is by design and is part of the application lifecycle process. Each developer would get the latest code from source control, and then check in their changes according their organization's development methodology. As part of this check in they can link the check-ins. This allows a build to then be created, and we gain a level of traceability since each work item (user story, feature, bug, and so on.) is linked to the check-ins in that build. This also allows test projects to be automatically executed when the build is generated.
Once the virtual machine has started, ensure that it has Internet access, and that you have used the admin user provisioning tool to associate your O365 account with the administrator account of Operations.
Before you start this, especially when working in a team, we must rename the VM to make it unique across our team; see the There's more... section for details on this.
To connect Visual Studio to VSTS, follow these steps:
- Create a folder for your projects, and underneath a subfolder with your initials, or others that make the folder unique, within your team; in my example, I chose C:ProjectsTFS.
- Start Visual Studio.
- You will be presented with the licensing page. Use the page to log in to the account used to create the project within VSTS. Which could be either your Microsoft account, or Work (O365) account.
- On the top toolbar, select Team and then Manage connections.
- The Team Explorer will open, under default layout, on the right-hand side. On this pane, select Manage Connections | Connect to Team Project:
- This will open the Connect to Team Foundation Server dialog, in the Select a Team Foundation Server drop-down list and select your VSTS site.
- Select your project in the lower portion of the dialog, as shown in the following screenshot:
- After pressingConnect, Visual Studio is connected to your project.
- We have one final step before we continue; we have to configure our workspace so Visual Studio knows which folders are under source control and how they map to VSTS. On Team Explorer, click on Configure workspace under the Project section. This will show the Configure Workspace section at the top of the Team Explorer.
- Do not press Map & Get.
- Press Advanced....
- The Edit Workspace dialog will look similar to the following screenshot:
For Operations development, we will need to map a projects folder and the Operations local packages folder (the application source code, or metadata as it is often referred to) to two different folders in VSTS. The Projects folder is the one we created earlier, which was C:ProjectsSB in my case. The Operations local packages folder is C:AOSServicePackagesLocalDirectory.
- In my case, the project is B05712_AX7_DevelopmentCookbook, so I will configure the dialog as shown in the following screenshot:
- Press OK.
- You will then be told that the workspace has been modified, and if you want to get the latest code. Either option has no effect if we are the first developer, but it is a good habit to always press Yes.
Source control in Operations has come a long way in this release, mainly because our development tool is now Visual Studio and that the source files are now actual files in the file system. Operations no longer needs special code to integrate with a Team Foundation Server.
The reason we have two folders is that our projects don't actually contain the files we create when writing code. When we create a file, such as a new class, it is created within the local packages folder and referenced with in the project. This also means that we can't just zip up a project and e-mail it to a co-worker. This is done by connecting to the same VSTS project or using a project export feature.
When working with multiple developers, one often overlooked task is to rename the virtual machine. This has gotten easier with each update, and the steps we take at the current release are as follows:
- Use Computer management to rename the machine. Use something like project ID and your initials for this; for example, B05712SB.
- Restart the virtual machine.
- Use the SQL Server Reporting Services configuration utility so that it references the correct server name.
- Renaming a VM (https://ax.help.dynamics.com/en/wiki/visual-studio-online-vso-machine-renaming/)
- Configuring your VSTS mapping after a code upgrade (https://ax.help.dynamics.com/en/wiki/configuring-your-vso-solution/)
When creating a new project, it is usually a new Package and a new Model. This keeps things simple, and there is usually no benefit in separating them. You may wish to create a test project in a different Model in the same solution, but you may not wish to deploy the test projects to live.
There are two types of projects: an extension project and an over-layer project. Over-layering means modifying the source code of Operations, and requires a code upgrade for each application hotfix. Extension projects work on delta changes to the standard object, or using delegates to affect code execution. Extension projects shouldn't need a code upgrade when application hotfixes are applied. Avoidance of over-layering cannot be overstated, in the time this book was being written Platform and Foundation have been locked, meaning that the over-layering must be removed. The ability to write good code through extension has been improved with each release, and with clever design the need to over-layer has been significantly reduced.
We will use extension projects exclusively, in order to to avoid conflicts with future upgrades. They make it possible to service the environment without having to deploy a new build of the custom solution. This is very exciting for ISV solutions, but also very important for VAR and end-user customers.
See the There's more... section for information on the relationship between packages, models and projects.
Startup Visual Studio and ensure that we are correctly connected to VSTS. As of the current release, you must start visual studio as an administrator.
To create the project, follow these steps:
- Under the Dynamics 365 menu, choose Model Management | Create model....
- The Model name is named as we would in AX 2012, and should be named like a new type, such as <prefix><area/module><ShortName>.
- Complete the first steps as follows:
In our case, our company is called Contoso, so our prefix will be Con, the area of change is an existing module (WHS) and it is for general extensions (extending standard objects without customization).
It is therefore named ConWHSGeneralExtensions. You should use your own prefix and prefixes, and the name for explained further in the There's more... section.
Your organization's name.
ISV / vertical solution / add-on: ISV
VAR / Partner solution / add-on: VAR
Customer solution / add-on: CUS or USR
The customer layers were traditionally used to segregate a customer's global solution layer from the requirements of each country implementation.
The layer technology is processed very differently for the extension projects, and has lost some significance in this release.
Leave as 188.8.131.52
You can update this to maintain a version of the model. This does not auto-increment and is usually left as default.
A full description of the model for other developers to read.
Model display name
Leave as default, which should be the Model name.
- Press Next.
- In the Select package page, choose Create new package.
- Press Next.
- We are now offered a list of packages that we can reference, these are listed as package's name and the models that the package contains, check ApplicationSuite and press Next.
- The two check boxes, Create new project and Make this my default model for new projects, should both be checked.
- Press Finish.
- This opens the New Project dialog. The project name is usually the same as the package and Model name; then, enter the package name in the Name field.
- The Location field must be changed; it will create the project in the default project folder, but we linked C:Projects<initials/username> to source control. The project must be created under this folder. So, in my case, Location must be C:ProjectsSB.
- The Solution name field should be left as the project name.
- Ensure that both Create directory for solution and Add to source control are checked.
- Press OK.
To see what we just did, we can simply look at the results. Use Windows explorer to navigate to the local packages folder, which is usually, C:AOSServicePackagesLocalDirectory. There, you will see the following structure, for the example package, ConWHSGeneralExtensions:
This is a package folder
This is a model folder with a subfolder per type
This contains a descriptor file for each model
This system managed folder for the Xpp metadata for all models in the package. This holds compiler metadata information about each element, not the actually source code. This includes the methods in a class, the type of method, the parameters, and so on.
We would never normally change anything here, but there are exceptions:
- If two developers create a different package at the same time, they can both get the same model ID, in which case, bad things start to happen. The solution is to check out the model's descriptor xml file in the Source Control Explorer and manually change the ID to the next number.
- You may decide that a standard package should be deleted, such as the tutorial or the sample fleet management solution. You can do this by simply deleting the package folder. Should you want to remove a standard model, you can delete the model folder, but you must also delete the relevant model descriptor file from the package's Descriptor folder. Obvious care needs to be taken, as you can't get it back!
The first point about can be solved by nominating a person to create packages and models.
If you look in the Source Control Explorer in Visual Studio, you will only see that the Projects folder has been added. This is correct. The Metadata folder will only appears when we create new elements.
When a solution is designed, it will be done by breaking the solution into packages of functionality. This is a normal design paradigm that has now been implemented (and, to an extent, enforced) within Operations. This means that our solution design will now define the various packages, and how they depend on each other. In the case of Operations, the package is a deployable unit that becomes a distinct DLL.
We can make a hotfix to a package and, technically, deploy it separately to other packages in the solution. Although this is possible, we would normally create a release of packages as a Deployable package. A Deployable package is a collection of one or more packages that contains both the built package code of one or more packages, and the routine required to install them. This process is simplified using a build server that performs the build process for us, executes any tests, and creates Deployable packages that we can then apply to our test environment.
There is a further level within Operations, which is a Model. A Model is a subset of elements, such as classes, within a package and can be used to move code from one development system to another, for example. A Model can only belong to one package, and a Package can contain one or more Models. Each package becomes a DLL, that has to have references added in order to 'see' elements in order packages. Because of this we should use a limited number of packages. As a guide we tend to have one package for the main stream, and one for reporting and business intelligence. To simplify management of development tasks, we tend to have a project per specification / Technical Design Document (TDD), all within the main or reporting packages, simplifying multi-developer projects. Just like working on complex C# projects, we can perform code merges, branching, and shelving within VSTS.
Layers has been a core part of prior releases from its first release, but is no longer that significant. As a partner we still use the VAR layer, and recommend the same guidelines as before to customers as before, but since we avoid over-layering this feature will not be covered in this book.
The following diagram shows a typical Package, Model, and Project structure:
Operations does not use namespaces. Neither packages nor models equate to a namespace. A model simply implies a scope, but all types must be globally unique; even in different models and packages. A name space would allow a class to have the same name as another class in a different namespace.
Therefore, every element must be globally unique by type; this includes models, packages, and every element in the application metadata. So, we will still need prefixes. Even if we create an extension of an element, such as a form, we must change the name so that it is guaranteed to be globally unique.
For example, if we wanted to create an extension of the WHSLoadTable table, it will call the WHSLoadTable.extension object by default. As our customer might want an add-on that also adds fields to this table, we need a want to ensure that the element is unique.
The best way to do this would be to use our prefix, which is Con in our case. To make it obvious of where the element is used, we use the package name as the suffix, for example, WHSLoadTable.ConWHS. There is no official best practice available for this, but the point to remember is that all elements of a type must be globally unique - and extensions are no exception.
Before we can get stuck into writing some code, we need to set up some parameters. Many settings described here are good for all projects, but some you may wish to change, depending on the scenario.
This follows the previous recipe, but can apply equally to any Operations project. Just load up Visual Studio and the project you wish to configure.
This will be split into two parts: generic options for all projects, Operations options; and project specific parameters.
Before we do either, we should always have the Application Explorer open, which is hidden by default. This is the Application Object Tree (AOT) of prior versions. This is opened from the View menu.
To configure the generic options for all projects, follow these steps:
- Select Options from the Dynamics 365 menu.
- The default option in the left-hand tree view is Debugging; the options here are usually fine. The Load symbols only for items in this solution option affects debugging and should be left checked for performance of the debugger. We would uncheck this if we want to trace code that calls code outside of the current package.
- Select the Projects option on the left and check Organize projects by element type. When adding new elements to the project, it will automatically create a sub folder in the project for the element type. This makes organization much easier to maintain.
- The other two options should be left blank. Although the Synchronize database on build for newly created project option can be useful, this database synchronization takes time, and it is usually preferable to do this as required. That is, before you run it.
- The Best practices node lets you choose which best practice checks you wish to be executed on build. This detail is beyond the scope of this book as the checks required are case specific.
These are usually fine as default for development, but we often want to test our code using the sample data that comes with the virtual machine.
To set up the common parameters, follow these steps:
- Right-click on the project in Solution Explorer and choose Properties.
- To save time whilst debugging, you select which object you wish to start with. To start with the form SalesTable, set the Startup Object Type option to Form, and Startup Object to SalesTable.
- Set Company to USMF or any other company you wish to start with when debugging.
- Leave Partition as initial. These are now only supported for certain unit test scenarios.
- If you wish to always synchronize the database on build, you can set Synchronize Database on Build. My advice is to do this manually, as required after the build completes.
You may notice that we can change the Model in the project's parameters. Our advice is, don't do it. To change the project's Model also means that the folders have to be moved in the local packages folder.
Most projects have some kind of user interface, and therefore we need to display text to the user other than the field names. The best practice method to do this is to use a label file. The label file contains a language specific dictionary of label IDs and the translation.
Standard elements tend to have the legacy label IDs of an @ symbol, followed by a three-digit label ID and a number. This format worked well for the past 15 years, but the prefix was potentially limiting, especially to aid ISVs. Labels are no longer restricted to three digits, which helps Microsoft attain one of its goals of making ISV add-ons easier to write, maintain and adopt.
The choice of how many and which packages need a label file depends on the solution design.
It isn't a terrible idea for an end user customer solution to have one package just for labels that are re-used by each package. This does mean that we run the risk of using a label out of context. You may choose to use a standard label for Name on personal record, only for the label to be changed by the original developer to something specific to the original context, for example, Product name.
We tend to create a label file for each package as this ensures that the package can correct and change labels without worrying about regression in other Models.
To get started, open Visual Studio, and the project in question, in my case I will continue with the ConWHSGeneralExtensions project.
To create the label file, follow these steps:
- Right-click on the project and select Add | New item... or use the keyboard shortcut, Ctrl + Shift + A.
- Choose Labels and Resources from the Operations Artifacts list.
- From the list on the left, select Label File.
- In the Name field, enter a short, but unique label name, in my case ConWHS. I want it to be as short as possible, but be completely sure it will be globally unique, regardless of any future add-on we may choose to install.
- Press Add.
- In the Label file wizard, leave Label file ID as default.
- Press Next.
- In the language selection, move the languages from the left-hand list into the right-hand list using the buttons. Only leave languages selected that you will maintain. This involves creating a label in each language file.
- Press Next.
- Check that the Summary page is correct, and press Finish.
The creation is straightforward. The process creates a text file on the disk that contains a tab-separated list of label IDs and translations.
When a label is selected against a control, it will be given a label file ID that ensures it is unique. In our example, the label file ID was ConWHS. As we create a label, it will be given the IDs in the sequence @ConWHS:ConWHS1, @ConWHS:ConWHS2, and so on.
In our example, the label IDs given to the control will be @ConWHS:ConWHS1. This seems needlessly long. Since, we can actually specify the label ID manually, we can choose to enter a shorter ID per label, generating a label such as @ConWHS:L001, or enter a memorable name as an ID, where the ID would then become @ConWHS:ItemNotExists.
Currently, the maintenance of labels can be time consuming, in that, we do not have a translation list per label ID as we did in Dynamics AX 2012, but a separate file per language. This is targeted for improvement, and may change by release. The concept, however, will remain the same.
When writing labels for variants of the same or similar languages, we can copy and paste the labels between files. Expand the label file to the lowest node to the file with a .txt extension, and right click on it to select Open With.... Choose Notepad from the list.
Each label will have two lines, one for the label, and the other for the comment, as shown in the following extract from an en-gb label file:
ConWHS2=The type of vehicle
VehTransCompleteHT=Complete, and finalise the vehicle inspection
You can than translate to the desired language and paste it into the target label file, again by opening the txt file in Notepad. You must do this from within Visual Studio, otherwise the file may not be checked out from source control. Be careful, as it will not validate that there aren't duplicates or file formatting errors.
If you intend to write add-ons, you should always maintain the en-us language file. You will get compilation warnings that the label ID does not exist, if you do not. If you are to release the software to a region with a variant of a language (en-au, en-gb, en-ie, en-us, and so on), please use the correct translation, as not only will it make your add-on more professional and global, but some terms have completely different meanings. For example, stock means inventory in en-gb, but means financial share holdings in en-us.