AX2012: Metadata service

Dynamics AX 2012 allows other programs to access its application metadata (like information about data types, tables, labels etc.) by WCF services. This solution has several advantages compared to an access via Business Connector (e.g. in security, configuration or when called from non-NET. applications).

How to use the metadata service is described very well on MSDN, so I warmly recommend to read that (see links below). I’m going to show just another example, similar to those on MSDN.

The implementation of a .NET application using the metadata services composes of few simple steps:

  1. Create a Visual Studio project.
  2. Add a service reference. WSDL for the metadata service is (by default) located at an address with format http://servername:8101/DynamicsAx/Services/MetadataService – so the valid address in the AX2012 Beta virtual machine is http://AX5-W8R2-01:8101/DynamicsAx/Services/MetadataService.
    Adding the reference activates magic of Visual Studio and proxy classes, configuration files etc. are generated in background.
  3. Create a client instance and call the required operation (=method).

The following example represents a console miniapplication, acception a label ID and returning the label text (in the default language). A console application is used just for demonstration porposes, a similar logic could be called in practice internally by a larger application.

using System;
using System.Text.RegularExpressions;
using AxMetadataServiceTest.MetadataServiceReference;
 
namespace AxMetadataServiceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Specify label ID: ");
            string labelId = Console.ReadLine();
 
            if (Regex.IsMatch(labelId, @"^@[a-zA-Z]{3}\d+$"))
            {
                var client = new AxMetadataServiceClient();
 
                try
                {
                    LabelMetadata labelMetadata = client.GetLabelMetadataById(new string[] { labelId })[0];
 
                    if (labelMetadata.LabelString == labelId)
                    {
                        Console.WriteLine("Label {0} was not found", labelId);
                    }
                    else
                    {
                        Console.WriteLine("{0}: {1}", labelId, labelMetadata.LabelString);
                    }
                    client.Close();
                }
                catch
                {
                    client.Abort();
                    throw;
                }
            }
            else
            {
                Console.WriteLine("Incorrect label ID format");
            }
        }
    }
}

Just few comments about this program:

  • Names of namespaces depends on your choice, so they can vary in your case.
  • Although AxMetadataServiceClient class (or rather its parent ClientBase) implements IDisposable, you should prefer Close() / Abort() calls to the using statement. It’s because Dispose() calls the Close() method and it can cause an exception, which presents a potential problem. (This not-completely-fortunate implementation has some historic reasons.)
  • If a non-existing label ID is specified, GetLabelMetadataById() suprisingly don’t throw an exception nor return null (as an array element) but it returns an instance containing the given (non-existing ID) in all properties. Therefore I detect non-existing labels by if(labelMetadata.LabelString == labelId) conditon.

Useful links:

MSDN: Metadata Service
MSDN Walkthrough: Calling the Metadata Service
MSDN Walkthrough: Using the Metadata Service to Get Table Field Labels
Discussion about Dispose() in ClientBase