AX Life Cycle Services and BPML’s

Life Cycle Services is a cloud-based collaborative workspace that customers and partners can use to manage their Dynamics AX projects from pre-sales into operations. One component of LCS is the Business Process Modeler which is used to create, view, and modify business-process libraries and flowcharts.

Firms can load their BPML (Business Process Master List) structure into LCS and document each process or activity (depending upon which is more applicable to the actual task performed by the business user) using the AX Task Recorder. The Task Recorder can record a process in AX as a user performs the actions. A video is saved and a Visio-like diagram generated. When the various process recordings have been completed, they can be uploaded to LCS to be shared.

Once in LCS, the various business processes can be analysed to highlight a number of items including possible security issues and conflicts.

Configuration

Configuring the Task Recorder is straightforward with experience. The help documentation and error handling is limited.

• Task Recorder is part of Dynamics AX 2012 R2 CU7 and later

• The AX client application must be “Run as Administrator” to function properly

• The client does not need to be running on the AOS server

Parameters

The file path to store the recordings should be a network share that everyone has full access to. Failure to use such a path will cause issues when compiling the package.

1

Framework

Framework and Industry can be used to better align business processes to standards, but in their simplest form, they can be used to maintain distinct BPML’s. At present only a single framework has been configured “Acme”.

2

Industry

In this case I am using Industry to delineate the different offices of the firm.

3

Hierarchy Levels

Acme’s BPML follows industry standards and is broken down into four levels for the TOR instance. Note the Advanced mode selection which is required for imports.

4

BPML Import

The screenshot below shows a section of Acme’s TOR BPML source file in Excel:

5

This template has been defined by Microsoft. Note that columns A and G must not contain any special characters and are used to build the hierarchy.

To import the BPML, launch the Task Recorder, switch to the Settings tab, and click on ‘Import Hierarchy’. Note: your existing hierarchy should be empty before doing this. Browse to the Excel file and press ‘Validate’. You cannot import unless the validate process passes.

6

Once the BPML has been imported, the hierarchy will be visible in the Task Recorder:

7

The actual business processes can now be recorded against each node in the hierarchy.

Recording

To record a business process, select the relevant leaf node in the Task Recorder BPML (1), choose the applicable Module for the task (2), Usage profile (3) and press the ‘Record’ button (4):

8

If you receive an error message stating “Application Module is Required for Recording”, ensure (2) is filled in. Windows Media Player must be installed and you must run AX as an Administrator.

The Task Recorder will automatically minimise to the task bar. Perform the steps in AX required to execute an example of the specified task. Do the absolute minimum number of actions required to accomplish the task. Keeping mouse clicks and data entry to a minimum will ensure a simpler, easier to understand model. Bring the Task Recorder up from the task bar and press ‘Stop’ when complete. The node colour will have updated indicating that a BPML item has now been recorded and attached.

9

If you made a mistake during your recording, just select the node (which will now have a blue arrow) and press the ‘Clear node’ button on the ribbon.

Packaging

Basics

Once the recordings are done, they need to be packaged up to be imported into the Lifecycle Services site. Ensure the correct Framework and Industry are selected, then press the ‘Build Package’ button.

10

A message box will appear stating that the process has been added to the batch. Depending on the size of the package to be built, this process can take some time. Progress can be viewed in the AX client at System Administration > Inquiries > Batch jobs. Filter on your name.

The compiled file will exist at the location specified in the Path field in the Parameters form outlined earlier in this post.

11

Navigate to the Lifecycle Services site at http://lcs.dynamics.com and login.

Click on your company’s AX Implementation project:

12

Then using the breadcrumb bar at the top of the page, click the drop down arrow and choose ‘Business Process Modeler’:

13

Click on the ‘Upload’ button under ‘My libraries’ to create a new library. Fill in the appropriate fields and click the ‘Upload’ button:

Browse to the location where the axbpm file you generated using the batch job from the Task Recorder was saved, and press ‘Open’.

A progress bar will appear at the bottom of the page detailing the upload progress. The Upload Status can be viewed at the top of the page and will start with a status of ‘In queue’. When it is complete, it will be available under the ‘My libraries’ section.

Note that the processing can take some time depending upon the size of your model file.

The resulting library will appear with the hierarchy and any recordings included:

14

Performance, Size and Appending

The more business processes with recordings, the larger the compiled axbpm file will be. Without any recordings at all, the Acme axbpm basic file containing just the complete BPML structure shown above is greater than 2 MB. Each recording adds a couple of megabytes at a minimum. This will lengthen the compile time and create files that are eventually too large to upload to LCS.

Lifecycle services permits inline editing of the BPML online, but it is not at a sufficient level of detail nor can video recordings be added. It is therefore preferable to clear your existing Task Recorder items, record news ones, compile and upload to LCS.

One option is to delete the axbpm file and associated folder from the file system. Another option is to clear them one by one in the Task Recorder. Click on the node in question and press the ‘Clear Node’ button on the ribbon.

New recordings can then be made as per normal in the Task Recorder. When complete press ‘Stop’. The node will change colour showing that a recording exists:

15

Then ‘Build the Package’ (on the Settings tab of the ribbon). Take the generated AXBPM file and upload it to LCS. When performing the upload, be sure to select the option that says “Attach Artifacts to an Existing Solution”.

16

The package needs to be processed like normal. It may take some time for the Status to update.

17

Once complete, the new recording is visible both at the top level of the BPML library:

18

And also down the tree:

19

Where the process and video have been appended to the leaf:

20

Posted in Dynamics AX | 1 Comment

AX 2012 CU7 Task Recorder – Distributed Environment

With Dynamics AX 2012 R2 CU7, a new Task Recorder has been released. The task recorder will allow you to record your business processes inside AX, generate a package, and upload them to Lifecycle Services (LCS).

It is generally suggested that you run the Task Recorder and AX client on the same server as your AOS to build the recordings. Many organisations restrict access to the AOS, so this is not always possible. When you are done recording the business processes and wish to generate package to upload to LCS, you are supposed to click on the ‘Build package’ button in the Task Recorder.

1

Unfortunately the error handling is limited in this version of the product. If the build process has an issue, quite often the button can be clicked, turns orange, and then returns nothing. The AOS server is attempting to build the package via a batch job, but if you are in a distributed environment, it’s quite likely the build is failing as it tries to find the recorded tasks. Check the Parameters form and ensure that the tasks are saved to a shared network location that both your AX client and the AOS have full access to.

2

The above is not a good location.

When the Build Package process is started successfully, you should see this message:

3

When the process completes, an axbpm file will be generated in the file path specified in the parameters screen. Be aware that this process can take a long time depending upon network and processor speed. I have seen small jobs take 15 minutes to complete. Progress can be viewed in the Batch job form under System Administration > Inquiries > Batch jobs > Batch jobs.

Posted in Dynamics AX | Leave a comment

Dynamics AX 2012 Expense Policies

Expense policies are a powerful tool that allow expense reports to be evaluated prior to submission. When editing/creating policies, it is important to verify the Effective date before saving the record:

1

If the Effective date is not set initially, a new rule must be created.

Another item to check with the policies is that is it applied to the organisation you are testing with. By default the Policy Organisations tab is collapsed. The system will allow you to create a policy and not assign any organisation to that policy.

2

Even if the Effective date is set your policy may not fire when expected. Try entering expense transactions for the current date and see if the policy fires – a future date would also be fine, but the system will not permit this.

If your policy works on transactions for the current date, but not transactions for any date prior, the problem is likely the Effective From / Valid From date field in the SysPolicyOrganization table. I have yet to find a way to edit this field from the front end user interface, but through the AOT, check that this field has an appropriate date. Even if a policy and policy rule have effective dates far in the past, if the organisation is not effective, no policy rules will apply.

3

Posted in Dynamics AX | Leave a comment

Enterprise Portal Policy Error

AX can sometimes through confusing error messages – this is definitely one of them.

When a user is attempting to save an expense report record on the Enterprise Portal:

A currency to convert to is required to retrieve exchange rate information.

1

After confirming that the usual suspects such a system currency are properly populated, it is advisable to double check that all of the custom expense report policies are properly configured.

In the screenshot below, the policy is improperly configured:

2

Whenever an amount is referenced in a policy, a currency parameter must be specified:

3

The expense report item will now submit properly.

Posted in Dynamics AX | Leave a comment

Creating a C# User Defined Function in Excel that Communicates with a WCF Service

Here is the business case: Your accounting staff wishes to query some figures from the financial system in Excel. To prevent a litany of copying and pasting, creating custom analysis services cubes, or taking the rather drastic measure of granting SQL access, it’s decided to create a custom User Defined Function in Excel. This UDF will query a WCF service that retrieves the information.

It is very easy to query a WCF service using an Excel VSTO add-in. Typically there is a custom ribbon with a button that, when clicked, goes off and retrieves the information. Unfortunately, VSTO add-ins built using Visual Studio do not have the ability to define custom User Defined Functions. The end result being targeted here is something like so:

Untitled

In order to do this, a Class Library project must be created and the result registered with Excel. There are a good number of examples of how to do this on the web, here is the summary:

 namespace YourNamespace
{
  [ClassInterface(ClassInterfaceType.AutoDual)]
  [ComVisible(true)]
  public class Functions
  {
    public Functions()
    {
    }

    /// <summary>
    /// A simple test function to ensure all is working
    /// </summary>
    /// <returns>A string</returns>
    public string Test()
    {
      return "Hello World";
    }
    
    /// <summary>
    /// Registration information
    /// </summary>
    /// <param name="type"></param>
    [ComRegisterFunctionAttribute]
    public static void RegisterFunction(Type type)
    {
      Registry.ClassesRoot.CreateSubKey(GetClsIdSubKeyName(type, "Programmable"));
      
      var key = Registry.ClassesRoot.OpenSubKey(GetClsIdSubKeyName(type, "InprocServer32"), true);
      if (key == null)
      {
        return;
      }
      key.SetValue("", String.Format("{0}\\mscoree.dll", Environment.SystemDirectory), RegistryValueKind.String);
    }

    [ComUnregisterFunctionAttribute]
    public static void UnregisterFunction(Type t)
    {
      Microsoft.Win32.Registry.ClassesRoot.DeleteSubKey(
          "CLSID\\{" + t.GUID.ToString().ToUpper() +
            "}\\Programmable");
    }

    private static string GetClsIdSubKeyName(Type type, String subKeyName)
    {
      return string.Format("CLSID\\{{{0}}}\\{1}",
          type.GUID.ToString().ToUpper(), subKeyName);
    }
  } // end class
}

 

So far, so good. The next step is to create a new UDF other than the Hello World one that connects to the web service. Standard procedure would be to add a Service Reference, create an instance of the client, call the method and be done with it. The problem is, you cannot call a Service Reference from a Class Library project easily. Using the above method, you will likely receive this message:

Could not find default endpoint element that references contract ‘UserService.UserService’ in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.

This occurs because the service definitions are stored in the app.config file of your class library project. Being a class library project, this does not get included when deployed. A number of solutions on the web suggest copying the service definitions from your app.config into the app.config of the application that calls your compiled class library. Unfortunately, when the calling application is Excel, this is not an option.

The solution to this is the revert to the “old school” method of dealing with WCF services and use the SVCUtil function to generate the WCF definition as a .cs file to be included in your project. This utility is most often installed here: C:\Program Files (x86)\Microsoft SDKs\Windows\vXXX\Bin. The command I ran is:

svcutil.exe http://ServerName/ServiceName/ServiceName.svc

Take the generated cs file, copy to your project folder, and include it in your project.

The straightforward method of connecting to a basic WCF service would be something like so:

 BasicHttpBinding binding = new BasicHttpBinding();

EndpointAddress remoteAddress = new EndpointAddress(“http://ServerName/ServiceName/ServiceName.svc”);
        
ServiceNameClient theService = new ServiceNameClient(binding, remoteAddress);
double result = theService.FinancialFigure(AccountNumber, StartDate, EndDate);

return result.ToString();
 

If however you are operating in a corporate environment, there is a good chance you will receive a message similar to this:

The HTTP request is unauthorized with client authentication scheme ‘Anonymous’. The authentication header received from the server was ‘Negotiate,NTLM’.

This is because the class library is attempting to connect to a WCF service that required authentication – in the example above, NTLM authentication.

Expand the C# code to include security settings:

 BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Ntlm;

EndpointAddress remoteAddress = new EndpointAddress(“http://ServerName/ServiceName/ServiceName.svc”);
ServiceNameClient theService = new ServiceNameClient(binding, remoteAddress);
 

Unfortunately that still did not work for me and I received this message:

System.ServiceModel.EndpointNotFoundException: There was no endpoint listening at http://ServerName/ServiceName/ServiceName.svc that could accept the message. This is often caused by an incorrect address or SOAP action.

This was an easy fix – just add /basic to the end of the service URL:

EndpointAddress remoteAddress = new EndpointAddress(“http://ServerName/ServiceName/ServiceName.svc/basic”);

That’s it! It took a while to put all the pieces together, but the result is a UDF in Excel that can call an NTLM secured WCF service.

Posted in Business Intelligence, Windows Apps | Leave a comment

AX4 WCF Errors

The AX Business Connector is extremely useful for accessing AX functionality and data from external programs. The connector has been around for a number of years and is still going strong. When testing a custom service leveraging the AX 4 connector using the WCF Test Client provided with Visual Studio 2012, the following error appeared:

The remote server returned an error: NotFound.

Obviously this is not all that helpful. Editi the web.config file and enabling debugging:

<behaviors>
  <serviceBehaviors>
   <behavior name="">
     <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true" />
                <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
                  <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
    <behavior name="AXServiceBehavior">
                <serviceMetadata httpGetEnabled="true" />
                <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
</behaviors>

After an IISReset, a more informative error appeared:

Could not load file or assembly ‘Microsoft.Dynamics.BusinessConnectorNet’ or one of its dependencies. An attempt was made to load a program with an incorrect format.

Which was strange as the file is present in the GAC.

The solution:

AX 4.0 is getting a bit long in the tooth – running on operating systems in development environments released in 2012 is bound to cause issues.

• After installing the Business Connector, restart the server even if not prompted
• Ensure the IIS application pool running the service is a supported .NET version (4.0 works)
• Ensure the account running the application pool has the required AX access levels
• Ensure the custom application is compiled with ‘Any CPU’
• Ensure the application pool is set to support 32 bit applications. IIS –> Select the Application Pool –> Advanced Settings –> Enable 32-bit Applications

Posted in Dynamics AX | Leave a comment

SSAS Calculated Member Based on Dimension Attribute

Creating a calculated member is a great way to add functionality to your cube. Most times calculated members are based entirely off values in your fact table, but every so often you need to pull a figure from a dimension. One such example would be if you have an exchange rate that is based on a location and is not time dependent.

img1

To use this value inside a calculated member, your calculation needs to leverage the ‘key’ property of your dimension. In the example below, the dimension is called ‘Location’ and has an attribute called ‘Exchange Rate’. The ‘Amount Base’ is the value we want to adjust from the fact table:

[Measures].[Amount Base]*[Location].[Exchange Rate].currentmember.properties("key")

The end result in the cube is as follows:

img2

The problem with this, is that as we are dealing with a calculated member, the amounts do not roll-up or aggregate to the parent levels. The calculation of the member needs to change to take this into account using a small amount of recursion:

IIF(
    IsLeaf([Location].[Exchange Rate].CurrentMember),
    [Measures].[Amount Base]*[Location].[Exchange Rate].currentmember.properties("key"),
    Sum([Location].[Exchange Rate].Children, [Measures].[Amount])
   )

This will in turn give you the desired results:

img3

Posted in Business Intelligence | 3 Comments

Save & Send from Excel issues with Outlook add-in

Add-ins are a great way to add custom functionality to Outlook. I have found that in certain circumstances they can introduce problems that are frustrating. A prime example of this occurs during the following scenario:
• There is add-in loaded in Outlook 2010 that adds a button to the email ribbon of the new message window
• A workbook that is opened yet not saved in Excel is then sent to an email recipient using the File –> Save & Send –> Send Using E-mail –> Send as Attachment
• The email is sent to a recipient
• Close the workbook without pressing Save
• The dialog prompting you to Save the Excel workbook briefly appears on the screen but then is hidden behind the window
• The only way to exit Excel is to close Outlook which brings the Save dialog to the foreground

This occurs even with the most basic add-in created using the Visual Studio 2010 wizard.

1

I have not been able to find a quick fix for this problem and instead have to export the code from the ribbon designer into XML, add the appropriate methods, then re-compile. To do this perform the following steps:

Open up the ribbon designer, right click and choose ‘Export Ribbon to XML’

2

This will create two new files Ribbon.cs and Ribbon.xml. Some instructions are generated at the top of Ribbon.cs which I will summarise below. It should be noted that if you have multiple ribbons in your solution, the next ribbon you click ‘Export Ribbon to XML’ on will only generate an XML file – you need to manually add code to the existing Ribbon.cs file. The code is documented below.

The first thing I tend to do is rename my Ribbon.cs and Ribbon.xml files to be something more meaningful. Visual Studio will prompt you to update the code to reflect this. In the screenshot below I changed Ribbon.cs to SharedRibbonCode.cs and Ribbon.xml to EmailRibbon.xml.

3

Now as per the generated instructions in the cs file, copy the following code to either ThisAddin, ThisWorkbook or ThisDocument. Obviously in this case I copied it to ThisAddin.cs

protected override Microsoft.Office.Core.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
   return new SharedRibbonCode();
}

In the SharedRibbonCode.cs file ensure the following function appears like so:

public string GetCustomUI(string ribbonID)
{
  return GetResourceText("OutlookAddinProblem.EmailRibbon.xml");
}

If you have more than one ribbon in your solution, change the above code to be a switch/case statement which returns the appropriate XML file based on the current window. For example:

public string GetCustomUI(string ribbonID)
{
      string ribbonXML = String.Empty;

      switch (ribbonID)
      {
        case "Microsoft.Outlook.Mail.Compose":
          ribbonXML = GetResourceText("OutlookAddinProblem.EmailRibbon.xml ");
          break;
        case "Microsoft.Outlook.Explorer":
          ribbonXML = GetResourceText("OutlookAddinProblem.MainWindowRibbon.xml ");
          break;
        case "Microsoft.Outlook.Appointment":
          ribbonXML = GetResourceText("OutlookAddinProblem.AppointmentRibbon.xml ");
          break;

      }
      return ribbonXML;
 }

Next you have to add callback functions in place of your events for the ribbon. As you can see from the screenshot at the top of this post, I have a single button. I right-click on the ComposeEmailRibbon.cs file and select ‘View Code’. The existing code is as follows:

private void button1_Click(object sender, RibbonControlEventArgs e)
{
  System.Windows.Forms.MessageBox.Show("Button Clicked!");
}

Copy that code to SharedRibbonCode.cs in the #region Ribbon Callbacks and change it slightly so it looks like so:

public void button1_Click(Office.IRibbonControl control)
{
  System.Windows.Forms.MessageBox.Show("Button Clicked!");
}

Note that if you have multiple ribbons in your project, you will need to ensure the controls have unique names across the ribbons.

Now that you have transferred the code, remove/delete the old ribbon designer code from the project. In this case I remove the following items:

4

Compile and install your add-in. The mentioned problem no longer exists!

Optional: Adding images. Using the XML file for your ribbon limits the visual design aspects. To add an image, add a getimage property to your XML:

<button id="button1" onAction="button1_Click" label="Click Me" showImage="false" getImage="GetImage" />

This refers to a GetImage function in the C# code:

public Bitmap GetImage(Microsoft.Office.Core.IRibbonControl control)
{
  switch (control.Id)
  {
    case " button1":
      return new Bitmap(Properties.Resources.Image1);
    case " button2":
      return new Bitmap(Properties.Resources.Image2);
    case " button3":
      return new Bitmap(Properties.Resources.Image3);
  }
  return null;
}
Posted in Windows Apps | Leave a comment

Excel 2007 vs 2010 SSAS Cube Functions

Sometimes a function that works perfectly fine in one environment totally fails in another. I was recently building a complex set of cube reports in Excel that caused me no end of grief. By complex I mean using a formula such as a CubeSet containing a TopCount that contains a Sum with a collection of dimensions and dimension sets.

I found that this would work perfectly fine under Excel 2010, and work up to a point in Excel 2007. Now I know Excel 2007 is getting a bit long in the tooth what with the 2013 preview available, but it is still prevalent in the corporate world. Microsoft did a lot of work with the MDX behind the scenes between the two versions, and although they contain much the same in terms of SSAS functions, they work quite differently.

The complex formulas mentioned above are dynamic. By that I mean based upon what the user selects in a collection of combo boxes, the content of the formulas (and consequently the dimensions selections used) change. For example, the user selects a different month from the combo box and the cube formula changes. What I found is that although this works perfectly fine under 2010, it often did not in 2007.

The solution is a simple one and not too much of a workaround. Simply build the full parameter string for your final function in another cell, then pass that cell to the function. For example:

Cell A1 contains =”TopCount([ADimension].Children, 5, Sum(” & Z1 & Q5 & AnotherRange & “), [YourMeasure].[Measure]))”

Cell A2 contains = CubeSet(CubeName, A1, “A Caption”)

That’s it!

What didn’t work in Excel 2007, yet did in 2010 was this:

Cell A2 contains = CubeSet(CubeName, TopCount([ADimension].Children, 5, Sum(” & Z1 & Q5 & AnotherRange & “), [YourMeasure].[Measure])), “A Caption”)

Posted in Business Intelligence | Leave a comment

SSRS Permissions

So you have just done a fresh install of SSRS 2008 R2. When you try to browse to http://yourServerName/reports you recieve this following message:

“YourUserName does not have the required permissions. Verify that sufficient permissions have been granted and Windows User Account Control (UAC) restrictions have been addressed.”

However if your run your web browser as an Administrator (Right click on IE and choose “Run as Administrator”), go to the same URL with the same user account, things work fine.

To resolve this all you have to do is set the permissions on the Home/root folder of the report server.

While running in admin mode, just click on the Folder Settings, New Role Assignment, and grant at least Reader permissions. Depending on your situation it might be advisable to grant the Reader permissions to Domain Users.

Posted in Business Intelligence | Leave a comment