Chapter 12. Microsoft Dynamics AX Services and Integration

In this chapter

Introduction
Types of Microsoft Dynamics AX services
Consume Microsoft Dynamics AX services
The Microsoft Dynamics AX send framework
“Consume external web services”
Performance considerations

Introduction

After your company deploys Microsoft Dynamics AX 2012, you can benefit from automating your business processes. But to realize the full potential of Microsoft Dynamics AX 2012 and get the maximum return on investment (ROI) from your Microsoft Dynamics AX 2012 deployment, you should also consider automating interactions between Microsoft Dynamics AX 2012 and the other software in your company and in the companies of your trading partners.

In many business scenarios, external software applications require access to information that is stored in Microsoft Dynamics AX. Figure 12-1 shows a few scenarios in which users access information that is managed in Microsoft Dynamics AX to accomplish a business task. It also shows sample scenarios in which Microsoft Dynamics AX accesses information that is managed in external applications. The arrows indicate the direction in which requests flow.

Common integration scenarios.

Figure 12-1. Common integration scenarios.

If you look at Figure 12-1 you can see that the users on the left side use applications that interact with the Microsoft Dynamics AX data store. These applications send request messages to Microsoft Dynamics AX (for example, to read a sales order). Sometimes, a response is expected from Microsoft Dynamics AX—in this example, the requested sales order document.

In all of these scenarios, another software application exchanges information with Microsoft Dynamics AX to accomplish a task:

  • The company’s CEO uses an interactive application (such as a Microsoft Office application) to analyze sales data that is stored in Microsoft Dynamics AX. The application communicates with Microsoft Dynamics AX on behalf of the CEO.

  • A salesperson who is visiting a prospect’s site uses a webpage or a mobile application to create a new customer account and then take the first sales order in Microsoft Dynamics AX from a remote location.

  • A sales processor enters a sales order and uses customer records that are stored in a customer relationship management (CRM) application to populate the customer section of the order in Microsoft Dynamics AX.

  • Trading partners submit sales orders as electronic documents, which need to be imported into Microsoft Dynamics AX periodically.

  • An accountant sends electronic payments or invoices to trading partners.

Performing these tasks manually—without programmatically integrating Microsoft Dynamics AX with other applications and business processes—doesn’t scale well and is error prone. With the Microsoft Dynamics AX services framework, you can encapsulate business logic—for example, functionality to create sales orders in Microsoft Dynamics AX—in Microsoft Dynamics AX services. You can then publish these services through the Application Integration Framework (AIF). These Microsoft Dynamics AX services can participate in a service-oriented architecture (SOA).

Note

SOA is a significant area of software development. A complete discussion of SOA is outside the scope of this book. Good information is available about SOA, including the Organization for the Advancement of Structured Information Standards (OASIS) specification “Reference Model for Service Oriented Architecture 1.0,” and the book Service-Oriented Architecture: Concepts, Technology, and Design by Thomas Erl.

The Microsoft Dynamics AX service framework provides a toolset for creating, managing, configuring, and publishing Microsoft Dynamics AX services, so that the business logic encapsulated in the service can be easily exposed through service interfaces. All service interfaces that are published through the Microsoft Dynamics AX service framework are compliant with industry standards and are based on core Microsoft technologies, including the software development kit (SDK) for Microsoft Windows Server, Microsoft .NET Framework, Windows Communication Foundation (WCF), and Message Queuing (also known as MSMQ).

In addition to the programming model and tools for implementing services, the Microsoft Dynamics AX service framework also includes the following:

  • A set of system services and document services that are included with Microsoft Dynamics AX 2012 and are ready for use.

  • A set of features for manipulating inbound and outbound messages, such as support for transformations, value substitutions, and so on.

  • An extensible integration framework that supports building new Microsoft Dynamics AX services and publishing them through a set of transport protocols such as Message Queuing, file, HTTP, or Net.tcp.

Note

The concept of service references has been removed from Microsoft Dynamics AX 2012.

Publishing Microsoft Dynamics AX services is a simple task that a Microsoft Dynamics AX administrator can do at run time. After a Microsoft Dynamics AX service has been published, external client applications, or service clients, can consume it.

Note

This chapter discusses configuration and administration tasks only where necessary to help you better understand the development scenarios. For additional details and code samples, see the Microsoft Dynamics AX 2012 system administrator documentation on TechNet (http://technet.microsoft.com/en-us/library/gg731797.aspx), or the Microsoft Dynamics AX 2012 Developer Center on MSDN (http://msdn.microsoft.com/en-us/dynamics/ax/gg712261).

Types of Microsoft Dynamics AX services

Microsoft Dynamics AX 2012 recognizes three types of services—system services, custom services, and document services—each with its own programming model. Microsoft Dynamics AX publishes metadata about available services and their capabilities in the form of Web Services Description Language (WSDL) files, which can be used for automatic proxy generation.

The following sections explain each type of service in more detail.

System services

Microsoft Dynamics AX system services are generic, infrastructural services that are not tied to specific business logic. System services are included with Microsoft Dynamics AX 2012 and are automatically deployed, so that Microsoft Dynamics AX components and external components can assume that these services are always available.

The functionality published by system services is often used by interactive clients that need to inquire about the capabilities or configuration of a specific deployment at run time. System services and their interfaces are not intended to be modified or reconfigured; they can only be hosted on the Application Object Server (AOS) and cannot be invoked through asynchronous transport mechanisms such as Message Queuing.

Microsoft Dynamics AX system services include the following:

  • Query service Publishes service operations that allow execution of existing (static) or ad hoc queries from service clients and returns results in the form of generic .NET datasets.

  • Metadata service Can be used to request information from Microsoft Dynamics AX about its metadata, such as tables, queries, forms, and so on, and thus, about its configuration.

  • User session info service Can be used to retrieve certain settings for the environment in which requests for the current user are executed; for example, a client application can use the user session service to request information about the current user’s currency, company, and time zone, among other things.

Custom services

You can use Microsoft Dynamics AX custom services to publish eligible X++ methods as service operations through integration ports for consumption by external client applications. To do that, you use the programming model for custom services to define metadata that determines the shape of the published service operations and data contracts. Custom services do not have to be tied to Microsoft Dynamics AX queries or tables. For example, you can use a custom service to publish functionality to approve an invoice or to stop a payment.

Note

Generally, Microsoft Dynamics AX document services are better suited for implementing services that publish standard operations that operate on queries or tables, such as create, read, update, and delete; these operations are often referred to as CRUD operations.

After you define the service operations and data contracts, you can publish your custom services. Their external interfaces can be configured through the respective system administration forms.

Custom service artifacts

To expose an X++ method as a custom service, you need to create the following artifacts:

  • Service implementation class A class that implements the business logic and exposes it through X++ methods.

  • Service contract Service-related metadata (no code). The most important service metadata consists of the service operations that are published to external service applications, and a reference to the X++ service implementation class that implements these service operations.

  • One or more data contracts X++ classes that represent the complex parameter types used for service operations. Data contracts are not needed for primitive data types.

Service implementation class

A service implementation class contains the code that implements the business logic to publish.

You can use any X++ class as a service implementation class. Service implementation classes don’t have to implement any interfaces or extend any super-classes. A class definition for a service implementation class MyService could look like this:

public class MyService
{
}

There are, however, constraints that govern which methods of a service implementation class can be published as service operations. Eligible methods are public methods that use only parameters with data types that can be serialized and deserialized; this includes most primitive data types in addition to valid Microsoft Dynamics AX data contracts. In addition, eligible methods must be declared as service operations in the service contract in the Application Object Tree (AOT).

Note

Every method that is intended to be published as a service operation must be annotated with the attribute SysEntryPointAttribute, which indicates whether authorization checks are to be performed by the AOS.

The following code shows an example of a method that can be declared as a service operation in the AOT, assuming the X++ type MyParam is a valid data contract. (For more information, see the section Data contracts, later in this chapter.)

[SysEntryPointAttribute(true)]
public MyParam HelloWorld(MyParam in)
{
  MyParam out = new MyParam();
  out.intParm(in.intParm() + 1);
  out.strParm("Hello world.
");
  return out;
}

Service contracts

Service contracts define which methods of a service implementation class are publishable as service operations and provide additional metadata that specifies how these methods should be published.

Note

Declaring a method as a service operation does not publish that method as a service operation.

To create a new service contract, you need to create a new child node in the AOT under the Services node; for example, MyService.

The newly created AOT node has a few properties to initialize before any methods of the service can be published as service operations:

  • Service implementation class This required property links the service interface to the service implementation class. In this example, the value is MyService.

  • Namespace Optionally, you can specify the XML namespace that should be used in the WSDL. If the XML namespace isn’t specified, http://tempuri.org is used by default.

  • External name Optionally, you can assign an external name for each service. In this example, the external name is left blank.

Finally, you need to add service operations to the service contract. To do this, expand the new AOT node, right-click, and then point to Operations > Add Operation.

Note that you can publish only methods as service operations that have been explicitly added to the service contract in the AOT.

Data contracts

A data contract is a complex X++ data type that can be used for input and output parameters in service operations. Most importantly, data contracts must be serializable. You can control how an X++ class is serialized and deserialized by the Microsoft Dynamics AX service framework through the X++ attributes DataContractAttribute and DataMemberAttribute:

  • DataContractAttribute declares an X++ class as a data contract.

  • DataMemberAttribute declares a property as a member of the data contract.

The following code shows a sample definition for the data contract MyParam, which is used in the previous example:

[DataContractAttribute]
public class MyParam
{
  int intParm;
  str strParm;
}

The following code shows a sample property that is included in the data contract:

[DataMemberAttribute]
public int intParm(int _intParm = intParm)
{
  intParm = _intParm;
  return intParm;
}

X++ collections as data contracts

If you want to use X++ collection types in data contract definitions, you need to ensure that all contained elements are of a data type that is supported for data contracts. Moreover, you need to provide additional metadata with the definition of the service method that uses the parameter, specifying the exact data type of the values in the collection at design time. You do this by using the X++ attribute AifCollectionTypeAttribute, as shown here for a sample method UseIntList():

[SysEntryPointAttribute(true),
  AifCollectionTypeAttribute('inParm', Types::Integer)]
public void UseIntList(List inParm)
{
  ...
}

The two parameters you need to pass into the constructor of the attribute are the name of the parameter to which the metadata is to be applied (inParm in the example) and the type of elements in the collection (Types::Integer in the example).

If you want to store X++ class types in your collection, you must also specify the class, as shown in the following example:

[SysEntryPointAttribute(true),
  AifCollectionTypeAttribute('return', Types::Class, classStr(MyParam))]
public List ReturnMyParamList(int i)
{
  ...
}

The three parameters that are passed into the AifCollectionTypeAttribute constructor are the name of the parameter (return), the type of the elements of the collection type (Types::Class), and the specific class type (MyParam).

Note

The parameter name return is reserved for the return value of a method.

Register a custom service

After you create all of the artifacts that are necessary for the custom service, you need to register the new service with the Microsoft Dynamics AX service framework. To register the service (in this example, MyService) with AIF, expand the Services node in the AOT, right-click the node you created earlier, and then point to > Add-Ins > Register Service.

As a result of the registration, you can now publish all declared service operations of your service. For more information, see the section Publish Microsoft Dynamics AX services, later in this chapter.

Document services

The term document services stems from the reality that businesses need to exchange business documents, such as sales orders and invoices, with their trading partners. Document services operate on electronic representations of such business documents.

The Microsoft Dynamics AX implementation of these business documents is also referred to as Axd documents. Document services are generated from Microsoft Dynamics AX queries. Wizards automate the process of quickly generating and maintaining all necessary artifacts for document services, with a configurable set of well-known service operations, from queries.

By nature, document services provide document-centric application programming interfaces (APIs)—that is, APIs that operate on Axd documents. Examples of document-oriented APIs for a sales order service include create sales order, read sales order, delete sales order, and so on. Each of these APIs operates on an instance of a sales order document. Create sales order, for example, takes a sales order document, persists it in the Microsoft Dynamics AX data store, and returns the sales order identifier for the persisted instance.

Document services are useful in scenarios that require the exchange of coarse-grained business documents, such as sales orders. In these scenarios, exchanged data is transacted and thorough data validation is important, data exchanges are expensive (for example, because enterprise boundaries are crossed), and response times are not critical. Sometimes, responses are not even expected (one-way communication).

The programming model for document services supports customizations to the artifacts that are generated. Microsoft Dynamics AX includes a set of document services that are ready to use. However, you can customize these services to better fit your business needs. The programming model for document services supports the data access layer features that have been introduced with Microsoft Dynamics AX 2012, such as surrogate key expansion, table inheritance, and date-effectivity. In other words, the Microsoft Dynamics AX service framework supports the development of services that use the tables that take advantage of the new functionality.

Document service artifacts

Just like custom services, all document services in Microsoft Dynamics AX 2012 require a service contract, a service implementation, and a data contract. For document services, these artifacts are generated from Axd queries; thus, their default implementation follows conventions and looks as follows:

  • Service contract Service-related metadata (no code) that is stored in the AOT nodes under the Services node, such as SalesSalesOrderService. The metadata includes the following:

    • Service operations that are available to external service clients.

    • A reference to the X++ service implementation class that implements these service operations.

  • Service implementation The code that implements the business logic that is to be exposed. For generated document services, the service implementation includes the following key elements:

    • Service implementation class An X++ class that derives from AifDocumentService and implements the service operations that are published through the service contract. For example, SalesSalesOrderService is the service implementation class for the service contract SalesSalesOrderService.

    • Axd <Document> class An X++ class that derives from AxdBase. Axd<Document> classes coordinate cross-table validation and cross-table defaulting. There is one Axd<Document> class for each document service. For example, AxdSalesOrder is the Axd<Document> class for SalesSalesOrderService. The AxdBase class, among others, implements code for XML serialization.

    • Additional artifacts Optionally, the AIF Document Service Wizard can generate additional artifacts such as Ax<Table> classes.

    Note

    In older versions of Microsoft Dynamics AX, an Ax<Table> class was generated for each table referenced from a query that was used to generate an Axd<Document> class. By default, in Microsoft Dynamics AX 2012, Axd<Document> classes use the Ax<Table> class AxCommon to access tables. The AxCommon class provides a default implementation for all Ax<Table> class functionality. Ax<Table> classes are needed only in advanced scenarios; for example, when a custom value mapping needs to be implemented for a table field.

  • Data object An X++ class that represents a parameter type and serves as a data contract. The parameter types that the Create New Document Service Wizard generates derive from AifDocument and represent business documents. For example, SalesSalesOrder is the data object that is created for the SalesSalesOrderService.

For a complete list of document service artifacts, see the “Services and Application Integration Framework (AIF)” section of the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/gg731810.aspx).

The following sections touch on a few selected topics for both Axd<Document> and Ax<Table> classes. For more information, see the “AIF Document Services” section of the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/bb496530.aspx).

Axd<Document> classes

Axd<Document> classes (such as AxdSalesOrder) extend the X++ class AxdBase. Among other things, Axd<Document> classes do the following:

  • Implement XML serialization for data objects.

  • Invoke value mapping.

  • Orchestrate cross-table field validation and defaulting.

Axd<Document> classes provide default implementations for XML serialization for all data objects that are used. These classes derive XML schema definitions used for XML serialization directly from the structure of the underlying query. The XML serialization code uses Microsoft Dynamics AX concepts such as extended data types (EDTs) to further restrict valid XML schemas and improve XML schema validation. Moreover, when generating XML schemas, Axd<Document> classes take the data access layer features that have been introduced in Microsoft Dynamics AX 2012 into consideration. For example, the generated XML schema definitions reflect date-effective table fields, expanded dimension fields, and the inheritance structure of the tables used in the underlying Axd query, if applicable; surrogate foreign key fields are replaced with alternate keys, if configured.

Axd<Document> classes always access tables through the Ax<Table> classes. During serialization, Axd<Document> classes rely on AxCommon or custom Ax<Table> classes to persist data to tables and to read data from tables.

Figure 12-2 illustrates the mapping between a Microsoft Dynamics AX query used for the Axd<Document> class AxdSalesOrder and the generated XML schema definition.

Correlation between the AOT query and the XML document structure.

Figure 12-2. Correlation between the AOT query and the XML document structure.

Axd<Document> classes also provide an API for orchestrating cross-table field validation and defaulting. Validation and defaulting logic that is relevant only for a specific Axd<Document> class, but not for all Axd<Document> classes that use the same table, can also be implemented in Axd<Document> classes.

Axd<Document> instances can be uniquely identified through AifEntityKeys, which consist of a table name (name of the root table for the Axd query), the field names for a unique index of that table, and the values of the respective fields for the retrieved record. In addition, AifEntityKeys holds the record ID of the retrieved records.

Ax<Table> classes

Ax<Table> classes (such as AxSalesTable and AxSalesLine) derive from the X++ class AxInternalBase. Unlike in earlier versions of Microsoft Dynamics AX, an Ax<Table> class is not needed for each table that is used in a document service; instead, the Ax<Table> class AxCommon has been introduced in Microsoft Dynamics AX 2012, which Axd<document> classes use by default to access tables.

Note

Document services that are included with Microsoft Dynamics AX 2012 might still rely on custom Ax<Table> classes for tables used in the underlying query, especially, if those services were created in earlier versions of Microsoft Dynamics AX, before the introduction of the AxCommon class.

However, there are scenarios in which custom Ax<Table> classes are required; for example, when parm methods for fields on the underlying table are needed to do the following:

  • Support calculated fields for a table in the Ax<Table> class.

  • Support a custom value mapping, which is different from the default implementation in AxCommon.

Note

Ax<Table> classes are often referred to as AxBC classes in both code and documentation.

Although optional in Microsoft Dynamics AX 2012, Ax<Table> classes can be generated as part of the document service with the AIF Document Service Wizard.

Create document services

You generate document services based on Axd queries by using the AIF Document Service Wizard. This section discusses a few selected aspects of generating and maintaining document services.

Create Axd queries Although general guidelines for working with Microsoft Dynamics AX queries apply to Axd queries, some additional constraints and guidelines apply:

  • Name Microsoft Dynamics AX queries that are used for document services with the prefix Axd followed by the document name. For example, the document service query for the document SalesOrder should be AxdSalesOrder. This is a best practice.

  • Only one root table for each query is allowed. You can associate the unique entity key that is used to identify document instances with this root table. For example, the entity key SalesId is defined on the AxdSalesOrder root table SalesTable.

  • If your query’s data sources are joined by an inner join, you should use fetch mode 1:1; if they are joined by an outer join, you should use fetch mode 1:n. If you don’t use these settings, your query and the service operations that use this query can yield unexpected results.

  • If you want to use a Microsoft Dynamics AX document service to write data back to the database—that is, if you need to support the service operation update—set the AOT property Update to Yes for all data sources that the query uses to generate the service.

Note

For security reasons, checks in X++ code by default prevent system tables from being used in queries that are used for document services.

Generate a document service To generate a document service from an existing Axd query, you can use the AIF Document Service Wizard. To start the wizard, on the Tools menu, point to Application Integration Framework > Create Document Service. This section provides a high-level description of the AIF Document Service Wizard and some important notes about how to use it.

In the wizard, you can select the service operations you want to generate for your service: create, read, update, delete, find, findKeys, getKeys, and getChangedKeys. If you select Generate AxBC classes when running the wizard, the wizard generates new Ax<Table> classes with parm methods for the fields of the tables used in the query.

The AIF Document Service Wizard uses the document name—which you enter on the first screen—to derive names for the generated artifacts. You can change the document name (and thus the derived names for the artifacts) in the wizard before the artifacts are generated. Names of AOT objects are limited to 40 characters. If you choose a document name that produces names that are too long for one or more artifacts, you may get error messages.

Once the wizard finishes, it displays a report of all generated artifacts and any errors encountered. You need to fix all errors before you start customizing the code that the wizard generates.

Tip

The wizard creates a new project for each generated service. It then adds the generated artifacts automatically to the created project.

You can use the Update Document Service dialog box to update existing document services; for example, to add a service operation that you had not selected initially.

Note

Although you can create and update document services manually, it is not recommended. Instead, always use the AIF Document Service Wizard to generate new document services from AOT queries and the Update Document Service dialog box quickly to update existing document services.

Microsoft Dynamics AX 2012 includes over 100 ready-to-use document services. These include services such as SalesOrderService and CustomerService. You can find a list of these services in the AOT Services node, or in the topic “Standard Document Services” in the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/aa859008.aspx).

For a more comprehensive discussion of the AIF Document Service Wizard and generating Axd<Document> and Ax<Table> classes, see the “AIF Document Services” section of the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/bb496530.aspx).

Customize document services

In many cases, you might need to customize the document services that you have generated from queries or that are included with Microsoft Dynamics AX 2012 to better fit your business needs. This section touches on some of the most common scenarios for customizing document services, including customizing the tables or queries, service operations, validation, defaulting, queries, and security.

Customize tables When you customize a table that is used by a document service (for example, by adding a column), you need to update the service implementation—that is, the Axd<Document> and Ax<Table> classes and the data objects—to reflect these changes.

Tip

Always enable best practice checks with the Best Practices tool to detect potential discrepancies between the table structure and the service implementation. If the best practice checks on any of your customized tables fail, you can use the Update Document Service dialog box to update the Axd<Document> class, Ax<Table> classes, and data objects to reflect the changes.

Caution

Because document services are based on Microsoft Dynamics AX queries, changes in the structure of a query that is used in a document service (for example, by adding a column to a table used in the query) inadvertently changes the data contract for that document service. Changes in external interfaces such as service interfaces can potentially break integrations that were built using the original data contract. Always consider the impact of changing queries or tables that are used in document services and apply common best practices for non-breaking service interface changes, such as not removing service operations, or data contract fields, and only adding optional fields.

Tip

If you use a static field list for the query from which an Axd document service is generated, you can prevent the data contract for the Axd document service from implicitly changing when a field is added to a table.

Add custom service operations You can change the behavior of any service operation by modifying its X++ implementation. In addition, you can add custom service operations to any document service by following the same steps used for adding service operations to custom services.

Customize validation logic Validation logic is crucial for enforcing data hygiene. Ideally, invalid data never is persisted in the Microsoft Dynamics AX data store.

Tip

To achieve this goal, always verify the validation logic of each service operation that you generate or customize to make sure that it meets your requirements.

Well-designed validation logic has the following characteristics:

  • Reusable Ideally, the same (generic) validation logic can be used from the Microsoft Dynamics AX client and from Microsoft Dynamics AX services. Keep in mind that non-generic validation code, code that applies only to the Microsoft Dynamics AX client or only to Microsoft Dynamics AX services, is also possible.

  • Well-performing Validation code runs whenever the respective Microsoft Dynamics AX entity is modified. As a consequence, one of your key goals for writing validation logic must be adequate performance.

  • Sufficient Validation logic must guarantee a sufficient level of data hygiene. You might have to trade sufficiency for performance in a way that satisfies your application’s requirements.

Validation code consists mainly of the following elements:

  • Code that orchestrates cross-table validation by invoking validation code that is implemented on the respective tables. This code is implemented in the respective Axd<Document> class methods prepareForSave, prepareForUpdate, and prepareForDelete. These prepareForXxx methods are called once for each Ax<Table> class that the Axd<Document> class uses.

  • Code that enforces table-level validation logic is implemented by the table methods validateField and validateWrite for maximum code reusability. These methods call specific validation methods, such as checkCreditLimit on SalesTable.

  • Code that performs document-level validation, which is implemented by the Axd<Document> class method validateDocument. This method is called immediately before changes are persisted to tables, and after the prepareForXxx methods have been called for each Ax<Table> class.

  • Code that performs validation after data has been persisted to the table, which is implemented by the Axd<Document> class method updateNow.

The following code, the prepareForSave method for AxdSalesOrder, is an example of cross-table validation. It calls validation methods for the Ax<Table> classes AxSalesTable and AxSalesLine (in addition to other Ax<Table> classes, which have been removed from this example):

public boolean prepareForSave(AxdStack _axdStack, str _dataSourceName)
{

    // ...

    switch (classidget(_axdStack.top()))
    {
        case classnum(AxSalesTable) :
            axSalesTable = _axdStack.top();
            this.checkSalesTable(axSalesTable);
            this.prepareSalesTable(axSalesTable);
            return true;

        case classnum(AxSalesLine) :
            axSalesLine = _axdStack.top();
            this.checkSalesLine(axSalesLine);
            this.prepareSalesLine(axSalesLine);
            return true;

        // ...
    }

    return false;
}

Customize defaulting logic You can customize the defaulting logic for table fields that is executed as part of creating or updating table rows. Defaulting logic helps increase the usability of both interactive client applications and Microsoft Dynamics AX service interfaces. It derives initial values for table fields from other data—such as values of other table fields—and thus, it doesn’t require explicit value assignments for the defaulted table fields. It also helps reduce the amount of data required to manipulate more complex entities, such as sales orders, while lowering the probability of erroneous data entry.

Well-designed defaulting logic has the following characteristics:

  • Reusable You should implement defaulting logic so that it is reusable—that is, so the same logic can be used regardless of which Microsoft Dynamics AX client (for example, a user interface or a service client) creates or updates the entity. In certain scenarios, the defaulting of table fields might require different logic, depending on whether the Microsoft Dynamics AX client is interactive (a user interface) or non-interactive (a request from a service client).

  • Well-performing Because the defaulting logic for a table field is invoked every time the field is set, its execution time directly affects the processing time for manipulating the entity, such as a sales order. In particular, try to avoid redundant defaulting steps—that is, setting a field value that is overwritten again as part of the same defaulting logic.

  • Sufficient To reduce the number of required fields for manipulating entities, as many fields as possible should be defaulted, while still meeting the performance goals.

Microsoft Dynamics AX 2012 still supports the approach to implementing defaulting logic that was supported in previous versions of Microsoft Dynamics AX. However, in Microsoft Dynamics AX 2012, mechanisms for tracking field states (such as not set and defaulted) have been added to tables, which means that you can implement defaulting logic directly in table classes. This allows for defaulting logic to be used not only by Axd<document> classes, but also from forms, and so on. Note that because now you can implement defaulting logic directly in the table class, an Ax<Table> class is not necessary for implementing standard defaulting code.

For more details about implementing and customizing defaulting logic in Microsoft Dynamics AX 2012 and information about how to customize document services in general, see the “AIF Document Services” section of the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/bb496530.aspx).

Security considerations

Service operations are entry points through which external applications can submit requests on behalf of users. As mentioned earlier, all X++ methods that are intended to be published as service operations must be annotated with the X++ attribute SysEntryPointAttribute, indicating whether the method is to be invoked in the context of the calling user. If so, authorization checks must be performed for tables accessed within the method. In addition, all concepts related to role-based security also apply to services and service operations.

System services are generally accessible and executed in the calling user’s context.

Because as the developer, you are in charge of the implementation of custom services, you must add the SysEntryPointAttribute manually to all service operations and create permissions when necessary.

When you generate document services by using the AIF Document Service Wizard, all generated service operations are automatically annotated with SysEntryPointAttribute. Moreover, the wizard attempts to infer all security permissions for the generated service automatically.

Tip

When using the AIF Document Service Wizard, always verify that the generated artifacts meet your requirements and adjust them if they don’t.

Publish Microsoft Dynamics AX services

After you create and customize your service, you need to publish it for external applications to be able to consume it. Developing a service and publishing a service are two separate and largely independent processes.

With the AIF, you can publish Microsoft Dynamics AX services through various transport technologies. In addition, the AIF provides a variety of configuration options that administrators can use to customize how service interfaces are published. This chapter limits the discussion of the AIF to publishing services through basic integration ports. For more information, see the services administration documentation for Microsoft Dynamics AX 2012 on TechNet (http://technet.microsoft.com/en-us/library/hh209600.aspx). You can also find guidance on how to develop, set up, and use concepts such as data policies, transformations, pipeline components, and value mappings.

For development and debugging purposes, you can easily publish registered custom services and document services through basic integration ports right from the AOT. You can also use service groups to ensure that services are deployed and activated automatically when the AOS is started by using the AutoDeploy property of the respective service group. This is useful when you need to be able to consume a service without administrator intervention; for example, to enable the service manually after deploying Microsoft Dynamics AX 2012.

To publish a service through a basic integration port, first, you need to add it to a service group in the AOT. Then you can deploy the service group with a default configuration using NetTcpBinding in WCF, right from the AOT. For more information, see the topics “Services, service operations, and service groups” (http://technet.microsoft.com/en-us/library/gg731906.aspx) and “Using basic integration ports” (http://technet.microsoft.com/en-us/library/hh496420.aspx) on TechNet.

Microsoft Dynamics AX services that are published through basic integration ports can only be hosted directly on the AOS. There are limited configuration options available for services published through basic integration ports. From the Inbound ports form (System Administration > Setup > Services And Application Integration Framework > Inbound Ports), you can activate and deactivate basic integration ports, you can use SvcConfigUtil to modify WCF configuration parameters, and you can enable logging for the respective ports.

Note

If you need to publish a service through a WCF binding other than NetTcpBinding, if you need to send unsolicited messages (outbound messages), or if you need more control over message processing and, for example, use XSLT transformations, you must create an enhanced integration port. You can create enhanced integration ports from the Inbound Ports form or the Outbound Ports form, respectively.

Discussions in this chapter generally assume that services have been published through basic integration ports unless noted otherwise. For details about how to publish services through bindings other than NetTcpBinding (for example, Message Queuing or file system adapters) using enhanced integration ports, how to create ports for outbound messages, and for additional configuration options, see the services and AIF documentation for Microsoft Dynamics AX 2012 on TechNet (http://technet.microsoft.com/en-us/library/gg731810.aspx).

Consume Microsoft Dynamics AX services

After you publish your Microsoft Dynamics AX services, external client applications can consume them and invoke the exposed business logic. For example, once the SalesOrderService is exposed, client applications can consume it to create or read Microsoft Dynamics AX sales orders.

This section highlights a few aspects of consuming Microsoft Dynamics AX services from client applications. As mentioned earlier, this chapter assumes that services are published through basic integration ports on the AOS. Services that are published through basic integration ports are accessible through Net.tcp.

For a more complete description of ways of publishing Microsoft Dynamics AX services, including the use of asynchronous adapters and related technologies, see the services and AIF documentation for Microsoft Dynamics AX 2012 on TechNet (http://technet.microsoft.com/en-us/library/gg731810.aspx).

Sample WCF client for CustCustomerService

If you want to consume a Microsoft Dynamics AX service that has been published through a basic integration port, you need to generate proxy classes from the WSDL of the service you want to consume. Typically, you do this either from within your development environment (Microsoft Visual Studio) or by using a command-line tool such as SvcUtil.

After you generate the proxy classes from the WSDL and add them to a project in your development environment, you need to write code to do the following:

  • Instantiate and initialize parameters.

  • Optionally instantiate and initialize a call context.

  • Instantiate a service proxy.

  • Consume the service operation.

  • Evaluate the response.

  • Handle errors and exceptions.

This section contains an example that illustrates what the code for consuming the service operation find() on the document service CustCustomerService (included with Microsoft Dynamics AX 2012) might look like.

For the following examples, assume that the document service CustCustomerService has been published through the service group MyServiceGroup and a Visual Studio project has been created. Also, in Visual Studio, the service reference MyServiceGroup was added by using the WSDL for the basic integration port MyServiceGroup. For details about where Microsoft Dynamics AX publishes WSDL files, see the topic “Locating the WSDL for Services” in the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/gg843514.aspx).

The following code snippets show C# code for the steps to consume the service operation find of the Microsoft Dynamics AX document service CustCustomerService.

First, you need to instantiate and initialize the parameters needed for the call. The service operation find accepts two input parameters: an optional call context and a query criterion that specifies which customer records should be returned. The following example retrieves all customer records in the company CEU with an account number greater than or equal to 4,000:

// instantiate and initialize parameters

// parameter: call context
MyServiceGroup.CallContext cc = new MyServiceGroup.CallContext();
cc.Company = "CEU";

// parameter: query criteria
MyServiceGroup.QueryCriteria qc = new MyServiceGroup.QueryCriteria();
MyServiceGroup.CriteriaElement[] qe = { new MyServiceGroup.CriteriaElement() };
qe[0].DataSourceName = "CustTable";
qe[0].FieldName = "AccountNum";
qe[0].Operator = MyServiceGroup.Operator.GreaterOrEqual;
qe[0].Value1 = "4000";
qc.CriteriaElement = qe;

Tip

You can use a CallContext object to execute a request in a different context than the default context, which is used if a null or empty CallContext object is used for a request. In the CallContext object, you can specify the company, language, and more.

Next, you need to instantiate a service proxy and consume the service operation find, which executes a query and returns matching entities:

// instantiate a service proxy
MyServiceGroup.CustomerServiceClient customerService =
    new MyServiceGroup.CustomerServiceClient();

// consume the service operation find()
MyServiceGroup.AxdCustomer customer = customerService.find(cc, qc);

Finally, you need to evaluate the response from the server, which can be either query results or exception and error messages:

// error handling (additionally, exceptions need to be handled properly)
if (null == customer)
{
    // error handling...
}

// evaluate response
MyServiceGroup.AxdEntity_CustTable[] custTables = customer.CustTable;
if (null == custTables || 0 == custTables.Length)
{
    // handle empty response...
}
foreach (MyServiceGroup.AxdEntity_CustTable custTable in custTables)
{
    custTable...
}

Note

Exception handling and other common best practices for developing web service clients are omitted from the simplified code examples.

Here are some tips for working with document services:

  • Many document services support both service operations find (which returns all Axd documents in the result set) and findKeys (which returns only the entity keys for Axd documents in the result set). If you expect the response message for invoking find to be very large, you might want to use findKeys to retrieve the entity keys. You can then, for example, implement paging to retrieve the matching Axd documents in sizeable chunks.

  • When developing new services, it is usually useful to turn on logging on the server side. To do that, open the Inbound Ports form, deactivate the integration port that publishes the service group containing your service, enable logging in the Troubleshooting section of the Inbound Ports form, and then reactivate your integration port.

  • If a service operation returns large response messages, you may need to tweak the default settings in your WCF configuration files for both the service and the client. By default, both service and client WCF configurations allow messages of sizes up to 65,536 bytes. The maximum message and buffer sizes are defined through the parameters maxReceivedMessageSize and maxBufferSize in the binding section of standard WCF configuration files. Before changing these parameters, refer to .NET Framework developer documentation to understand implications and valid values for these parameters. The .NET Framework Developer Center is located at http://msdn.microsoft.com/en-us/netframework/aa496123.

Other service operations for custom or document services can be consumed in similar ways. For more information and code examples, see the Microsoft Dynamics AX 2012 SDK at http://msdn.microsoft.com/en-us/library/aa496079.aspx.

Consume system services

Unlike custom services and document services, system services are automatically published (on the AOS by using the NetTcpBinding) and are ready for consumption by client applications when AOS starts.

Like all Microsoft Dynamics AX services, system services publish metadata in the form of WSDL files, which you can use for proxy generation (see the previous examples). However, while the user session info service is published explicitly through an integration port (UserSessionService), similar to custom and document services, an integration port does not exist for the query service or the metadata service.

To provide an example of how to work with the metadata service and the query service, the following code example shows how to do the following:

  • Retrieve query metadata—the definition of a query named MyQuery—from Microsoft Dynamics AX by using the metadata service.

  • Convert the query metadata from the data contract used by the metadata service to the data contract used by the query service. This conversion is necessary although both data contracts are structurally identical (see the method ConvertContract in the following code example).

  • Add a range to the metadata object; in this case, include all rows with a value greater than 1996 for the Year column.

  • Execute the converted query definition by using the query service.

In .NET code, these steps could be implemented in a similar way to the code sample that follows. Assume that you’ve created a Visual Studio project and added the references MetadataService and QueryService by using the WSDLs for the metadata service and the query service, respectively.

For details about where Microsoft Dynamics AX publishes WSDL files, see the topic “Locating the WSDL for Services” in the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/gg843514.aspx).

// instantiate proxies
var metadataClient = new MetadataServiceReference.AxMetadataServiceClient();
var queryClient = new QueryServiceReference.QueryServiceClient();

// retrieve query metadata
MetadataService.QueryMetadata[] query =
  metadataClient.GetQueryMetadataByName(new string[] { "MyQuery" });

// convert query metadata
QueryService.QueryMetadata convertedQuery = ConvertContract
  <MetadataService.QueryMetadata, QueryService.QueryMetadata>(query);

// add a range to the query metadata object
QueryDataRangeMetadata range = new QueryDataRangeMetadata()
{
  Enabled = true,
  FieldName = "Year",
  Value = ">1996"
};
convertedQuery.DataSources[0].Ranges = new QueryRangeMetadata[] { range };

// initialize paging (return 3 records or less)
QueryService.Paging paging = new QueryService.ValueBasedPaging();
((QueryService.ValueBasedPaging)paging).RecordLimit = 3;

// instantiate a service proxy
QueryService.QueryServiceClient queryService =
  new QueryService.QueryServiceClient();

// execute the converted query with the range, receive results into .NET dataset
System.Data.DataSet ds =
  queryClient.ExecuteQuery(convertedQuery, ref paging);

Note that although the QueryMetadata definition is identical in both the query service and the metadata service, the proxy generator generates an identical class in two different namespaces, one for each service. A ConvertContract method that implements the conversion of two contracts of the same structure by using generics could look similar to the following code:

static TTargetContract ConvertContract<TSourceContract, TTargetContract>
    (TSourceContract sourceContract)
        where TSourceContract : class
        where TTargetContract : class
{
  TTargetContract targetContract = default(TTargetContract);
  var sourceSerializer = new DataContractSerializer(typeof(TSourceContract));
  var targetSerializer = new DataContractSerializer(typeof(TTargetContract));
  using (var stream = new MemoryStream())
  {
    sourceSerializer.WriteObject(stream, sourceContract);
    stream.Position = 0;
    targetContract = (TTargetContract)targetSerializer.ReadObject(stream);
  }
  return targetContract;
}

As mentioned earlier, the CallContext is used to override the default context (such as company and language) in which a request is executed. A CallContext is optional for all service requests; if it is not present in a request, the request is executed using default values for the CallContext properties.

In Microsoft Dynamics AX 2012, the WSDL files for the query service and the metadata service do not contain the XML schema definitions for CallContext. Consequently, proxies generated from the WSDL files for those services do not include proxy classes for CallContext; however, CallContext can still be used for the query service and the metadata service the same way as it is with other services. To use CallContext in requests sent to the metadata service or the query service, you need to add a service reference to an integration port (such as UserSessionService), which generates the proxy classes necessary for CallContext. You can then instantiate and initialize a CallContext object and add it to your request, as shown in the following code:

// get OperationContextScope (see WCF documentation)
using (System.ServiceModel.OperationContextScope ocs =
    new System.ServiceModel.OperationContextScope((queryService.InnerChannel))) {

  // instantiate and initialize CallContext (using class from other service)
  CustomerService.CallContext callContext = new CustomerService.CallContext();
  callContext.Company = "CEU";

  // explicitly add header "CallContext" to set of outgoing headers
  System.ServiceModel.Channels.MessageHeaders messageHeadersElement =
  System.ServiceModel.OperationContext.Current.OutgoingMessageHeaders;
  messageHeadersElement.Add(
    System.ServiceModel.Channels.MessageHeader.CreateHeader(
      "CallContext",
      "http://schemas.microsoft.com/dynamics/2010/01/datacontracts",
      callContext));

  // initialize paging (return 3 records or less)
  QueryService.Paging paging = new QueryService.ValueBasedPaging();
  ((QueryService.ValueBasedPaging)paging).RecordLimit = 3;

  // instantiate a service proxy
  QueryService.QueryServiceClient queryService =
      new QueryService.QueryServiceClient();

  // consume query service using CallContext
  System.Data.DataSet ds =
      queryService.ExecuteStaticQuery("MyQuery", ref paging);
}

Note

The query service returns query results in chunks that are defined through a required paging parameter. The paging algorithms assume that queries use relations with FetchMode set to 1:1 (AOT property). The query service produces an error message for queries that use relations with FetchMode set to 1 :n.

Please refer to the product documentation for further details on the CallContext or capabilities of system services.

Update business documents

In many scenarios, you need to update data in already-existing Axd documents, such as to add a sales line to a sales order or to update a customer address. Through the service operation update, document services support different semantics for document-centric updates: full updates and partial updates.

For the following examples, assume that the standard document service SalesSalesOrderService has been added to a service group named MyServiceGroup and published through a basic integration port named MyServiceGroup.

Apply a full update

Full updates are the default behavior for document services. To use this mode, add code to your client application to do the following:

  • Read the document.

  • Apply changes to the document.

  • Send the updated document back to the server.

  • Handle errors, if any.

The following C# code provides a conceptual example of how to apply a full update to an existing sales order:

// instantiate and initialize callContext, entityKeys, serviceOrderService
MyServiceGroup.EntityKey[] entityKeys = ...
MyServiceGroup.CallContext callContext = ...
MyServiceGroup.SalesOrderServiceClient salesOrderService = ...
...

// read sales order(s) (including document hash(es)) using entityKeys
MyServiceGroup.AxdSalesOrder salesOrder =
    salesOrderService.read(callContext, entityKeys);

// handle errors, exceptions; process sales order, update data
...

// persist updates on the server (exception handling not shown)
salesOrderService.update(callContext, entityKeys, salesOrder);

Apply a partial update

In many scenarios, full updates are inefficient. Imagine a large sales order with many sales lines—having more than 1,000 is not uncommon. If you use a full update, you would have to retrieve the entire sales order with all sales lines, apply your changes to the one sales line you want to update, and then send back the entire sales order—including all unchanged sales lines. This operation can be costly when you consider the validation and defaulting logic invoked on the server for each sales line.

Instead of performing a full update, you can apply a partial update. Partial updates use the same service operation as full updates do: update. However, with partial updates, you can send partial documents that contain only the changed (added, modified, or deleted) data. For child elements, documents sent in partial update requests contain processing instructions specifying how to handle each (child) record included in the partial document to avoid ambiguity. Consequently, the process for updating documents by using partial updates contains one additional step:

  • Read the document.

  • Apply changes to the document. To take advantage of partial updates, ensure that you only send the fields back to the server that are either mandatory or that have changed.

  • Explicitly request the partial update mode and add processing instructions.

  • Send the updated document with the update request.

  • Handle errors, if any.

The following code provides a conceptual example of how to apply a partial update to a sales order:

// instantiate and initialize callContext, entityKeys, serviceOrderService
MyServiceGroup.EntityKey[] entityKeys = ...
MyServiceGroup.CallContext callContext = ...
MyServiceGroup.SalesOrderServiceClient salesOrderService = ...
...

// read sales order(s) (including document hash(es)) using entityKeys
MyServiceGroup.AxdSalesOrder salesOrder =
    salesOrderService.read(callContext, entityKeys);

// handle errors, exceptions; process sales order, update data
...

// example: update the first sales order and mark it for partial update
AxdEntity_SalesTable[] salesTables = salesOrder.SalesTable;
salesOrder.SalesTable = new AxdEntity_SalesTable[] { salesTables[0] };
// document-level directive, requesting a partial update
salesOrder.SalesTable[0].action = AxdEnum_AxdEntityAction.update;

// table-level directive, requesting to delete the first sales line
AxdEntity_SalesLine[] salesLines = salesOrder.SalesTable[0].salesLine;
salesOrder.SalesTable[0].SalesLine = new AxdEntity_SalesLine[] { salesLines[0] };
salesOrder.SalesTable[0].SalesLine[0].action = AxdEnum_AxdEntityAction.delete;

// remove child data sources w/o updates (DocuRefHeader, etc.) from salesTable
...

// persist updates on the server (exception handling not shown)
salesOrderService.update(callContext, entityKeys, salesOrder);

Note

In XML request messages, these processing instructions are reflected through occurrences of the XML attribute action. This is true for both XML messages sent to asynchronous adapters and for Simple Object Access Protocol (SOAP) messages sent to synchronous WCF services. For more details, see the “AIF Document Services” section of the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/bb496530.aspx)

Optimistic concurrency control

The services framework relies on optimistic concurrency control (OCC) to resolve conflicts when multiple concurrent update requests occur. To be able to detect whether a document has changed since it was last read, and to avoid inadvertently overwriting such changes, the service framework uses document hashes to identify versions of a business document.

Document hashes are computed for a specific document instance from its contents; they are derived not only from the root-level data source (such as the sales header) but also from all of the joined data sources (such as a sales line). In other words, if a field in any table that is included in the business document changes, the document hash changes too.

To obtain the document hash for a business document, your code must first read the document. It can then use the document hash that was returned inside the document in a subsequent update request.

Tip

Caching a document for a long time on a service client without refreshing it increases the probability of update requests being rejected because of colliding updates from other client applications.

Invoke custom services asynchronously

Because publishing a service is separate from developing the service, both custom services and document services can be published through the supported transport mechanisms; more specifically, a custom or document service’s operations can be published synchronously (for example, by using the Net.tcp or HTTP protocol) through basic integration ports, as shown in the previous examples, or they can be published asynchronously (for example,. by using the file system adapter or Message Queuing) through enhanced integration ports. Administrators can select various options to configure how service operations are bundled and published at run time and to configure logging, among other things. For more information about publishing services through enhanced integration ports, see the services and AIF documentation for Microsoft Dynamics AX 2012 on TechNet (http://technet.microsoft.com/en-us/library/gg731810.aspx).

When consuming Microsoft Dynamics AX services synchronously, typically generated service proxies take care of producing and consuming the XML that is exchanged between the client application and Microsoft Dynamics AX. However, when consuming Microsoft Dynamics AX services through asynchronous transports, you need to make sure that the request messages comply with the XML schema definitions for the AIF message envelope and the business document as expected by the Microsoft Dynamics AX service framework. For more information about how to get the XML schema definitions (XSDs) for message envelopes, see the “AIF Messages” section in the Microsoft Dynamics AX 2012 SDK (http://msdn.microsoft.com/en-us/library/aa627117.aspx)

The following code example shows a sample XML message that can be sent asynchronously from a client application to Microsoft Dynamics AX to consume the service operation MyService.HelloWorld(MyParam in) of a custom service that was discussed in a previous example (see the Custom services section, earlier in this chapter). It illustrates how the service name, the service operation name, and the structure of the input parameters map to the corresponding elements of the XML request message. It also shows how you can specify the context in which the request is executed: through the Header element, which recognizes the same properties the CallContext knows in the case of synchronous service interfaces:

<?xml version="1.0" encoding="UTF-8"?>
<Envelope
    xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
  <Header>
    <!-- Service operation: "MyService.HelloWorld(MyParam)" -->
    <Company>CEU</Company>
    <Action>http://tempuri.org/MyService/HelloWorld</Action>
  </Header>
  <Body>
    <MessageParts
        xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">

      <!-- Complex input parameter: "MyParam in" -->
      <in xmlns="http://tempuri.org"
          xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:b="http://schemas.datacontract.org/2004/07/Dynamics.Ax.Application">

        <!-Property of complex input parameter: "in.b" -->
        <b:intParm>0</b:intParm>
      </in>
    </MessageParts>
  </Body>
</Envelope>

Note

To run this example, you need to create an enhanced integration port that is configured to receive files asynchronously. That integration port must publish the service operation MyService.HelloWorld.

So far, this chapter has discussed how Microsoft Dynamics AX functionality can be published through services for consumption by external client applications and how external client applications can consume these services. But what if you want to send unsolicited data out of Microsoft Dynamics AX? The following two sections discuss how to use the Microsoft Dynamics AX send framework for sending unsolicited data asynchronously.

The Microsoft Dynamics AX send framework

AIF provides APIs and infrastructure for using Microsoft Dynamics AX services to send unsolicited one-way messages. The Microsoft Dynamics AX client has features like the Send Electronically button on several forms that allow users to transmit business documents (such as invoices) as unsolicited one-way messages through outbound integration ports. For information about how to configure outbound integration ports, see the services and AIF documentation for Microsoft Dynamics AX 2012 on TechNet (http://technet.microsoft.com/en-us/library/gg731810.aspx).

Microsoft Dynamics AX doesn’t rely on external document schema definitions to be provided by the remote receiving application; it uses its own format instead—the same Axd<Document> class-based XSDs that are also used as data contracts for published Microsoft Dynamics AX services.

Implementing unsolicited one-way messages requires the following two steps:

  • Implement a trigger for transmission (design time).

  • Configure an enhanced outbound integration port for sending documents (administration time).

Implementing a trigger for transmission

You can implement a trigger for transmission by using either the AIF Send API or the AxdSend API.

AIF Send API

The Send API features a set of methods that can be used to send unsolicited one-way messages from Microsoft Dynamics AX by means of integration ports, through which the consumers can pick up the messages. This API sends a single message: the body of the message contains the XML that is generated by invoking the read service operation of the AIF document service referenced by the serviceClassId (it must reference a class that derives from AifDocumentService) with the parameter entityKey.

To see a working example of how you can use this API, look at the code behind the method clicked for the button SendXmlOriginal on the form CustInvoiceJournal. The API methods are defined on the class AifSendService and include the method submitDefault:

public static void submitDefault(
    AifServiceClassId serviceClassId,
    AifEntityKey entityKey,
    AifConstraintList constraintList,
    AifSendMode sendMode,
    AifPropertyBag propertyBag = connull(),
    AifProcessingMode processingMode = AifProcessingMode::Sequential,
    AifConversationId conversationId = #NoConversationId
)

By using the two optional parameters in the preceding signature, processingMode and conversationId, you can take advantage of the parallel message processing feature for asynchronous adapters:

  • processingMode Specifies whether messages can be moved from the AIF outbound processing queue to the AIF gateway queue in parallel (AifProcessingMode::Parallel) or whether first-in-first-out (FIFO) order must be enforced for all messages (AifProcessingMode::Sequential).

  • conversationId If this is specified, AIF moves the message from the AIF outbound processing queue to the AIF gateway queue in FIFO order, relative to all other messages with the same conversationId. The order relative to other messages with different conversationIds isn’t guaranteed.

AxdSend API

The AxdSend API provides functionality to send unsolicited one-way messages. The user selects the outbound integration port through which the documents are sent at run time. If more than one document needs to be sent, the user also selects the exact set of entities at run time. This feature has been implemented for several Microsoft Dynamics AX document services, such as AxdPricelist and AxdBillsOfMaterials.

The AxdSend framework provides default dialog boxes for selecting integration ports and entity ranges and allows the generation of XML documents with multiple records. You can use the framework to provide specific dialog boxes for documents that require more user input than the default dialog box provides.

The default dialog box includes an integration port drop-down list and, optionally, a Select button to open the standard query form. The query is retrieved from the Axd<Document> class that the caller specifies. Many integration ports can be configured in AIF, but only a few are allowed to receive the current document. The lookup shows only the integration ports that are valid for the document, complying with the constraint set up for the read service operation for the current document.

The framework requires minimal coding to support a new document. If a document requires the user to just select an integration port and fill out a query range, most of the functionality is provided by the framework without requiring additional code.

An example dialog box for the AxdSend framework is shown in Figure 12-3.

The Send Document Electronically dialog box for bills of materials.

Figure 12-3. The Send Document Electronically dialog box for bills of materials.

If an Axd<document> requires a more specific dialog box, you inherit the AxdSend class and provide the necessary user interface interaction to the dialog box method. In the following code example, an extra field has been added to the dialog box. You just add one line of code to implement parmShowDocPurpose from the AxdSend class and to make this field appear on the dialog box:

static public void main(Args args)
{
   AxdSendBillsOfMaterials axdSendBillsOfMaterials;
   AifConstraintList       aifConstraintList;
   AifConstraint           aifConstraint;
   BOMVersion              bomVersionRecord;

   axdSendBillsOfMaterials = new  AxdSendBillsOfMaterials();
   aifConstraintList       = new AifConstraintList();
   aifConstraint           = new AifConstraint();

   aifConstraint.parmType(AifConstraintType::NoConstraint);
   aifConstraintList.addConstraint(aifConstraint);

   if (args && args.record().TableId == tablenum(BOMVersion))
   {
       bomVersionRecord = args.record();
       axdSendBillsOfMaterials.parmBOMVersion(bomVersionRecord);
   }

   // added line to make the field appear on the dialog box
   axdSendBillsOfMaterials.parmShowDocPurpose(true) ;

   axdSendBillsOfMaterials.sendMultipleDocuments(
      classnum(BomBillsofMaterials),
      classnum(BomBillsofMaterialsService),
      AifSendMode::Async,
      aifConstraintList);
}

Sorting isn’t supported in the AxdSend framework, and the query structure is locked to ensure that the resulting query matches the query defined by the XML document framework. Because of this need for matching, the AxdSend class enforces these sorting and structure limitations. The query dialog box shows only the fields in the top-level tables because of the mechanics of queries with an outer join predicate. The result set will likely be different from what a user would expect. For example, restrictions on inner data sources filter only these data sources, not the data sources that contain them. The restrictions are imposed on the user interface to match the restrictions on the query when using the document service’s find operation.

Configure transmission mechanisms

For details about configuring enhanced outbound integration ports and other administrative features related to sending unsolicited messages asynchronously by using the Microsoft Dynamics AX send framework, see the services and AIF documentation for Microsoft Dynamics AX 2012 on TechNet (http://technet.microsoft.com/en-us/library/gg731810.aspx).

Consume external web services from Microsoft Dynamics AX

Web services are a popular and well-understood way of integrating applications that are deployed within an enterprise’s perimeter, or intranet. Examples of such applications include enterprise resource planning (ERP) applications, CRM applications, productivity applications such as Office, and so on.

Integrating applications with third-party web services over the Internet has also become viable and in many cases is the preferred approach for quickly adding new functionality to complex applications. Web services can range from simple address validation or credit card checks to more complex tax calculations or treasury services.

Similar to sending unsolicited data asynchronously by using the Microsoft Dynamics AX send framework, you can customize Microsoft Dynamics AX to send requests to external web services—in other words, to consume external web services. Because consuming external web services implies a tight coupling with the respective web service (and usually involves a service proxy for the web service), and because Visual Studio provides a rich set of tools for building such integrations, you should create a Visual Studio project and build a .NET dynamic link library (DLL) that contains the code to consume the external web service. You can then add this library as a reference to Microsoft Dynamics AX and write X++ code that calls methods exposed by this .NET library.

Note

The Microsoft Dynamics AX service framework does not provide any tools specific to writing code to consume external web services. The concept of service references as it existed in Microsoft Dynamics AX 2009 has been removed from Microsoft Dynamics AX 2012, and the related AOT node no longer exists.

Performance considerations

To meet performance requirements for a specific Microsoft Dynamics AX implementation scenario, planning for and sizing of the hardware infrastructure is critical. For guidance on how to size your deployment properly, see the Microsoft Dynamics AX Implementation Planning Guide (http://www.microsoft.com/en-us/download/details.aspx?id=4007).

By default, integration ports process all request messages in sequence. This is true for both incoming and outgoing request messages. To increase the number of request messages that can be processed, you can use the AIF parallel processing capabilities in combination with additional AOS instances. For more information about how to configure inbound ports for parallelism and how to use extensions to the AIF Send API, see the “Services and AIF Operations” section of the Microsoft Dynamics AX 2012 system administrator documentation on TechNet (http://technet.microsoft.com/en-us/library/gg731830.aspx).

Note that for synchronous WCF services, request processing is inherently parallel.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset