All Blog Posts - page 9
Apr 30, 2012 - Changing a Model Name When Using TFS on AX 2012
Filed under: #daxmusings #bizappsOne of the challenges we recently faced was renaming a model on an AX 2012 system that is hooked up to TFS. As it turns out, it’s not a big deal, really.
- Make sure everyone is off the system, shutting down the AOS may be a good idea too.
I’m not certain how much trouble you would be in changing the model while the AOS is running or someone is on the system, but at the very least you want to avoid issues with the TFS paths.
- Rename the model folder in TFS (optional).
Open up Visual Studio, browse to the model folder in source control and rename the model folder. Now, keep in mind that technically the name of the folder in TFS does not have to match the name of the model (although I find it much more intuitive of course).
- Edit the model.xml file in TFS to reflect the new name.
I’m not entirely certain what AX uses the model manifest for after it’s been created, but we use it in our build scripts, and it’s probably just good bookkeeping to changing the name everywhere.
- Edit the vcsdef.xml.
the vcsdef.xml file resides in the Definition folder of your source control tree, and maps model names to folders in your source control. This comes back to the point that the folder name does not necessarily have to match the name of the model. The vcsdef.xml file has a
- Use AxUtil or the powershell cmdlets to change the name property of your model.
Using AXUTIL: axutil edit /model:MYMODEL /manifest:Name=MyModelNewName
Using PowerShell: Edit-AXModelManifest -Model MYMODEL -Property “Name = MyModelNewName”
Optionally you can also used the updated model manifest file to update the model store to the new name.
- Make sure you pull all the updated TFS stuff into your local AX workspace.
Depending on where you launched Visual Studio to make the changes, and depending what workspace you were using there, the vcsdef.xml file (and new folder name, model.xml, etc) may not be updated in the repository that your AX client is using. Make sure you pull the latest changes down!
- Restart AOS and AX 2012 won’t realize anything happened at all.
Log into AX and you shouldn’t have any problems with your renamed model.
Mar 16, 2012 - Blog Update and Convergence
Filed under: #daxmusings #bizappsI realize it’s been longer than usual for another update to appear on this blog. Don’t fear, there is more to come! We are experiencing the surge in demand due to the AX 2012 release, and our offices are buzzing like never before. To make things even more busy, I’ve become a first time father on March 1st, so there is even less time to write articles. Don’t worry, the content will start coming in again soon!
And of course… next week is Convergence! For those not attending, make sure you watch the keynote on the Convergence website to see where things are at, and where they’re going. For those who are attending, make sure to check out the computer labs for walkthroughs, demos and some good hands-on with the product. Several MCTs, including myself, will be supervising the labs to make sure you are getting started ok, and answering questions where possible. Make sure to come check us out. We will be together with the Microsoft AX support and product groups, so you have everything in one place…
See you in Houston! If you’re going to be there, let me know.
Feb 18, 2012 - Code Snippets in AX 2012
Filed under: #daxmusings #bizappsI wanted to post a little follow-up on an article presented by my fellow blogger Brandon George. In his post XppSource Exposed: Inserting Code Snippets he explains to his colleague the mysterious source of the code snippets you can insert by typing keywords and pressing TAB in the Dynamics AX 2012 editor. Although the XppSource class in the AOT does contain the code for those snippets, it is not where they originate.
In this post I will show you how to add your own code snippets. Since they are X++ code, you can even pop up a dialog to ask for parameters.
First of all, what are we talking about? Well, in the Dynamics AX 2012 editor, you can type certain keywords that trigger code snippets. For example, open a code editor window and type “whileSelect” (without quotes, and a capital S! this is case sensitive).
after the whileSelect statement, press the TAB key. You will see the code snippet pop in.
There is the XppSource class in the AOT, which does contain the code for these snippets. However, the real trigger is the EditorScripts class, which has existed for quite a few versions in AX, but was previously only available by right-click in the code editor, and going to the “Scripts” menu. Note that the menus you get to see are somewhat intelligent, and you will get different templates if you have an editor window open for a job versus a method on a class. For example, if you add a new method on a class, you delete all the default code, and type “parm” and press TAB.
This will open a dialog to enter some parameters to create a new parm method.
There are templates for parm, main, etc. These are however not available when you are editing a Job, for example.
The EditorScripts class works by naming your methods after the “Scripts” menu path from the code editor. For example, the scripts menu has sub-menus named “addIns”, “sendTo” and “template”. You will notice there are a bunch of methods in the class that are prefixed with “addIns_”, “sendTo_” and “template_”. This is exactly how the scripts menu is built, it parses the method names and creates submenus. As you have probably guessed by now, by adding new methods with the “template_” prefix, you can add your own code snippets. Note that you can create new sub-menus as you want.
So let’s create a new code snippet. We’ll add a template method for a “find” method on a table. Now, the EditorScripts class knows a lot about the code window you have open. It knows the object you are editing code on, for example. So thinking about a find method… The EditorScript should know pretty much everything there is to know. If it knows what table we are editing on, it can find out what the primary key fields are. If it knows what the table is and what the primary key fields are, it can automatically create the code for the find method.
So, to follow the Dynamics AX practice of adding the code to the XppSource, we will start by adding a new method for “findMethod”.
Now, this code is fairly elaborate and sort of takes away of the point of this article about code snippets, but I figured it’s such a useful template to have that I would post the whole thing. I’m sure there’s room for improvement, but this gets the job done, feel free to leave your comments and questions below, let me know if you are using this!.<pre>Source findMethod(TableName _tableName, boolean _useReplacementKey = false)
{
DictTable dictTable = new DictTable(tableName2id(_tableName));
DictIndex dictIndex = new DictIndex(tableName2id(_tableName),
(_useReplacementKey && dictTable.replacementKey() != 0) ? dictTable.replacementKey() : dictTable.primaryIndex());
DictField dictField;
int fieldIndex;
if (dictIndex == null)
throw error(strFmt("Couldn't find primary index for table %1", _tableName));
// method signature returning the table
source += strFmt('public static %1 find(', _tableName);
// add the primary key fields as the parameters to the find method
for (fieldIndex=1; fieldIndex<=dictIndex.numberOfFields(); fieldIndex++)
{
dictField = new DictField(dictTable.id(), dictIndex.field(fieldIndex));
source += strFmt('%1 _%2, ', extendedTypeId2name(dictField.typeId()), dictField.name());
}
source += strFmt('boolean _update = false)\n');
indentLevel = 0;
this.beginBlock();
// Declare the table
source += this.indent() + strFmt('%1 %1;\n', _tableName);
source += '\n';
// Set update yes/no
source += this.indent() + strFmt('%1.selectForUpdate(_update);\n', _tableName);
// select firstonly
source += this.indent() + strFmt('select firstOnly %1 where', _tableName);
// add the primary key fields in the where clause
for (fieldIndex=1; fieldIndex<=dictIndex.numberOfFields(); fieldIndex++)
{
dictField = new DictField(dictTable.id(), dictIndex.field(fieldIndex));
source += '\n';
source += this.indent() + strFmt(' %1%2.%3 == _%3', ((fieldIndex>1) ? '&& ' : ''), _tableName, dictField.name());
}
source += ';\n';
source += '\n';
// return the buffer
source += this.indent() + strFmt('return %1;\n', _tableName);
this.endBlock();
return source; }</code></pre> So, next we need to create the method on the EditorScripts class that will call this source method and add it to the editor, based on the Scripts menu or the keyword assigned. Logically this goes under the "methods" sub-menu. So we will call our method "template_method_find". Note that the last portion of this name will be the keyword triggering the code snippet in the editor, and that the keyword is CASE SENSITIVE. Our new method will look like this:<pre><code>public void template_method_find(Editor editor) {
xppSource xppSource = new xppSource();
Source template;
str path = editor.path();
TreeNode treeNode = path ? TreeNode::findNode(path) : null;
TableName tableName;
#TreeNodeSysNodeType
if (treeNode)
{
treeNode = treeNode.AOTparent();
if (treeNode && treeNode.treeNodeType().id() == #NT_MEMBERFUNCLIST)
{
treeNode = treeNode.AOTparent();
if (treeNode && treeNode.treeNodeType().id() == #NT_DBTABLE)
{
tableName = treeNode.treeNodeName();
}
}
}
if (!tableName)
{
warning("Find method applies to tables only");
return;
}
template = xppSource.findMethod(tableName);
editor.insertLines(template); }</code></pre>Note that the whole treeNode section checks if this method is on a table. Optionally, you could add some code that prompts a dialog to ask for the table name in case the method is not on a table. Feel free to do so.
I tried to find a table without a find method, but I couldn’t quite find one right away (and that’s a good thing). But of course we can just try this anywhere. Let’s open the CustTable table in the AOT, and add a new method. Remove all the existing code and type “find” and hit TAB.
Yay! Observant readers have noticed that the method supports primary key versus alternate key (if you’re not sure what this means, check my article on RecId and Alternate Keys!).
Feb 16, 2012 - AX 2009 Troubleshooting Resources
Filed under: #daxmusings #bizappsThe Microsoft Dynamics AX support team has started a new blog dedicated to highlighting the top resources for troubleshooting issues with AX 2009. Aside from listing the issues and resources, they are hoping to engage the community via comments on the posts. Now that MSDN and TechNet are starting to catch up on useful information about the product, it’s nice to see some dedicated resources to troubleshooting.
You can find the blog on the Dynamics Community site.
Aside from this blog dedicated to troubleshooting, there is another blog from the support team that I’ve found very useful to subscribe to. Check out the “regular” blog of the AX Support team.
And of course, never forget the official Microsoft Dynamics AX forums.
Jan 24, 2012 - Enterprise Portal Web URL Lookup Error
Filed under: #daxmusings #bizappsGot this interesting info today on an issue with Enterprise Portal development.
When creating a new URL in the Web > Web Menu Items > URLs node in the AOT, you have to type in the relative URL to your SharePoint page in the URL property. There is an ellipsis lookup button that is supposed to allow you to lookup a page. However, when you click this button, you get the error message “Error in Url property error”. Apparently, this is not an AX issue, but there is Windows update to address this issue. You can find the download for the patch and more information on the Microsoft Support web site (KB907306).
After installing the update (I wasn’t required to reboot the server), I restarted my Dynamics AX client and all was well when I clicked the ellipsis button to lookup a page on SharePoint.
Jan 24, 2012 - Windows Phone 7 Must-Have Development Tools
Filed under: #daxmusings #bizappsNot AX related, unless you want to develop a 10-minute Windows Phone 7 app (see what I did there?).
In any case, came across this interesting post through twitter, which highlights some great tools for Windows Phone 7 developers. The Silverlight Spy looks really interesting, it’s somewhat like UISpy, but for Windows Phone 7 and some special features.
For this and other interesting WP7 development tools like the Isolated Storage Explorer and Metro Grid Helper, check out this blog post on Diary of Ninja.
Jan 18, 2012 - Importing Data to AX 2012 Using Excel Add-ins
Filed under: #daxmusings #bizappsI came across an extremely useful blog while reading Twitter today. Alex Anikiev has started posting a series of blog posts on importing data into AX 2012 using the Excel add-ins. He lists the steps necessary to fix issues as well as diagrams of the data models! Make sure to go through his blog archive.
I have not tried any of these but skimming through the articles they look very useful! Use any import information at your own risk!
The blog is located at http://ax2012exceldataimport.blogspot.com/, and currently has the following articles:
Generic Data Import Information and Setup Walkthrough
Import Customers Importing Vendors Importing Main Accounts Importing Products Importing Customer Transactions/Balances Importing Vendor Transactions/Balances Importing Ledger Transactions/Balances Importing Inventory Transactions/Balances Importing Sales Orders Importing Free Text Invoices Importing Purchase Orders
Jan 17, 2012 - Preview Pane on List Pages
Filed under: #daxmusings #bizappsPreview Panes are those sections at the bottom of list pages that show more information about the selected record in the list page’s grid. For a preview pane, you can use ANY type of part available in AX 2012 (Info Parts, Form Parts, Cues and Cue Groups). Info parts are best suited as a preview pane part. They are easily modeled in the AOT and work on both the rich client and Enterprise Portal. Cues and Cue Groups also work on both clients, however they are not your typical Preview Pane since they do not provide a list of data but rather a summation or count of records with a graphical representation. Form Parts work well as Preview Panes, however they have separate development paths for the rich client versus the Enterprise Portal. For use in the rich client, you develop a form in the AOT. For use on the Enterprise Portal, you need to develop a web user control.
When you test a preview pane, you may notice it shows up as a regular factbox on the list page. Generally, opening the list page form from the AOT seems to have some quirks. If you want to test a list page with its preview panes and factboxes, create a menu item. That way you can add it to the menu and open the list page in the client, or you can right-click the menu item and deploy the list page to the Enterprise Portal. If you are testing on the Enterprise Portal, you do not have to deploy the list page after making changes to it. You’ll need to “Refresh AOD” to pick up any changes to your list page. You can find that in the quick launch menu in the “Home” module on the Enterprise Portal.
Jan 6, 2012 - Enterprise Portal in AX 2012
Filed under: #daxmusings #bizappsOf course, first of all, happy new year! Oh, and: FIRST POST! :-)
With AX 2012, Enterprise Portal has also gotten an upgrade. It is now built on SharePoint 2010, and also hooks into the Enterprise Search features of SharePoint. As far as development goes, the new .NET story has simplified the use of proxies (of course), and MorphX list pages “just work” as EP pages without any extra effort (except clicking deploy). Of course there is a lot more to talk about!
I’m working on Enterprise Portal content for Microsoft, so it’s been EP round the clock for weeks now, and not quite done yet. Of course this brings a good opportunity to share a lot of that knowledge I’m gathering with all of you readers.
So, before I start writing EP articles for this blog to add to the AX 2012 Developer Resources, what kind of questions do you have? Any particular issues, general information, development questions, follow me on Twitter and send me your questions!
Dec 13, 2011 - Resolving Compile Errors and Generating CIL is not Optional
Filed under: #daxmusings #bizappsAll too often I visit clients or move in a code release to a production environment, only to find there are compile errors in the environment. This is totally unacceptable, and not just in a production environment. The existence of a compile error in a production environment is bad in itself, but it clearly shows there is an underlying problem going on in the development process.
Why is there a compile error in production, how did it get there? There are only 2 possibilities: 1) someone was WRITING/CHANGING code in production 2) there is a problem in the procedure of moving code into production
If someone was writing code in production, they should get a warning and a note in their employee file. Writing code in a production environment is one of the worst offenses a developer can make. I’ve known plenty of projects where developers did not have access to production at all. I absolutely love that idea because it forces proper procedures all around. I’ve seen consultants and developers complain about not having access to production to troubleshoot issues. If issues are severe enough they need a developer’s eye and possibly debugging, it’s time to take a backup of production and restore in an environment where investigation can be done (you should never have debugging on AOS enabled in production!). Contrary to some people’s beliefs, making an environment copy is an easy (and relatively quick) thing to do, and it is the right thing to do. Debugging in production or manipulating data in production using the table browser or SQL without having tested this (and its impact) in a copy of production first is just as bad of an offense…
The second possible scenario is a problem with code release procedures. I’ve talked about this topic before in the AX 2012 code deployment article, and this is a good illustration. Deployments to production should be done in a binary, compiled form. That implies that 1) the code was compiled and checked somewhere else and moved into prod in a compiled form, so no compile errors should exist in prod after the move 2) the code that was moved into prod is the exact same as where it came from and was tested
Compile errors in prod can result from missing objects in XPOs or having to do an XPO merge while importing and making a mistake. All the more reasons to not move XPOs. To quote my deployment article: “Moving XPOs is barbaric” (it’s becoming my slogan).
In either case, after moving in XPOs you should do a full compile anyway. At Streamline Systems we move layers or models, not XPOs. But even then we do a full compile after the binary code is moved in. It is an extra check that your code is ok, but more importantly it verifies that your layer works with the existing layers in the environment. What if a code change you made works by itself, but there is a customization in another layer that is now broken because of your change? You will not know until you do a full compile. And hopefully you already noticed that in a user acceptance testing environment (that has the same other layers as production) before you moved it into production. I guess layers being out-of-sync between production and a user acceptance testing environment could be considered a third reason for a production environment to have compile errors, but it comes down to a code release procedure issue as well.
Compiling brings me to my next topic. The way the X++ language works as a scripting language has gotten us spoiled over the years. The fact that X++ is a scripting language is exactly the reason why we are even talking about these issues. You can modify one object, compile it, and you’re good to go. If you just broke another object by doing this code change, you won’t know until run-time, or until you do a full compile of everything and find out. Think about traditional compiled development. For your code change to be incorporated, you have to recompile your whole library. If you make one code error or break something in another code file, your whole library will fail to compile and you can’t run anything anymore at all until that is fixed. Besides this being good practice, it totally makes sense. So now in AX 2012, we have the CIL generation. This generates .NET assemblies for all the X++ code. And guess what? If you have 1 compile error anywhere, the CIL generation will fail to complete. However, the .NET assemblies are used in batch jobs, services, and potentially other code being run explicitly in the CLR. (Check my previous article on X++ and CLR for details.) As soon as the CIL generator encounters ANY compile error, it will stop going any further (just like a regular compile in C# for example). So you may have two pieces of code that are totally independent of each other. But one of the two has a compile error and CIL generation will abort for BOTH.
So here are two major conclusions I leave you with: 1) If you have ANY X++ compile errors in your system, you may end up with NO CIL code at all, even if the compile error is in a different area of code 2) Without a full CIL generation you have a CRIPPLED AX environment. Your CIL code will either be the previously compiled binaries (without your latest code change), or it won’t be there at all. Batch jobs and services may not work at all, or have unexpected behavior based on the last good compile that happened.
So, resolving compile errors and having a completed full CIL generation in AX 2012 is NOT OPTIONAL. If you have compile errors in any of your environments, you should go back to your desk and start resolving them until they’re fixed, right now. Failing to do so will break AX 2012, for real.
Blog Links
Blog Post Collections
- The LLM Blogs
- Dynamics 365 (AX7) Dev Resources
- Dynamics AX 2012 Dev Resources
- Dynamics AX 2012 ALM/TFS
Recent Posts
-
GPT4-o1 Test Results
Read more... -
Small Language Models
Read more... -
Orchestration and Function Calling
Read more... -
From Text Prediction to Action
Read more... -
The Killer App
Read more...