Export (0) Print
Expand All
5 out of 6 rated this helpful - Rate this topic

How to: Call an AIF Web Service from C#

Dynamics AX 2009

This topic describes how to write a Web service client application in C# that calls a Web service that is exposed by Application Integration Framework (AIF).

AIF exposes Web services through Internet Information Services (IIS) which is installed with the Microsoft Windows operating system. You must install AIF Web services on the computer that is hosting IIS. The AIF Web services installation includes the information necessary to connect to the Application Object Server (AOS).

You can call Microsoft Dynamics AX Web services from C#, Visual Basic, or any other .NET Framework language.

Your C# application code relies on proxy classes to communicate with the Web server. These proxy classes are automatically generated by Microsoft Visual Studio 2008. Visual Studio reads the service definition that is provided by Microsoft Dynamics AX in the form of a Web Service Definition Language (WSDL) file. You must use the Content Pane in Microsoft Dynamics AX to generate the WSDL information that Visual Studio reads. Your C# program must run on a computer that uses the Web Services (WS) binding protocols to communicate with IIS.

This topic refers to several classes or methods that correspond to XML tags in AIF find service messages. For example, the XML tag <QueryCriteria> correlates to the C# class QueryCriteria. For more information about XML message tags for the find service message, see Example: Find Action.

You must create and configure various Web site features before an external application can call Web services that are provided through AIF.

Install AIF Web Services

You must make sure that the Microsoft Dynamics AX component named AIF Web services is installed. This component is not installed by default during the Microsoft Dynamics AX setup.

The following steps verify that AIF Web services component is installed.

  1. Rerun the setup.exe that installs Microsoft Dynamics AX.

  2. Click the Add or modify components option.

  3. Select AIF Web services. This install cannot succeed unless .NET Business Connector is already installed.

  4. As you click Next to continue through the forms of the setup wizard, you see a form that suggests a default name for the virtual directory. Write down the name for the virtual directory, for later reference.

    NoteNote

    For example, MicrosoftDynamicsAXAif50 is the default virtual directory name in Microsoft Dynamics AX 2009. The full virtual directory share path is \\<MyComputerName>\MicrosoftDynamicsAXAif50\.


  5. Proceed and finish the installation modification.

Add an AIF Web Site

In the client, you use the Content Pane to add a Web site. The new Web site is then displayed by utilities that report on your IIS installation.

  1. In the Content Pane, locate Basic, Basic Area, expand Setup, expand Application Integration Framework, and then click Web sites.

  2. In the Web sites form, add a record with a value of the full virtual directory share path noted earlier.

  3. In Application Integration Framework, click Services.

  4. In the AIF Services form, click Refresh to populate the form.

  5. Scroll to the row for the service you want, and select Enabled.

  6. In the AIF Services form, click Generate. This generates the service artifacts for all the services that are enabled. When the generation is complete, close the form.

Verify the Web Site in IIS

You can verify that your AIF Web site is known to IIS by using the Computer Management utility that is included with the Microsoft Windows operating system.

  1. In the Windows operating system, click Start, click Administrative Tools, and then click Computer Management.

  2. In the Computer Management window, expand Services and Applications, expand Internet Information Services (IIS) Manager, expand Web Sites, expand Default Web Site, and then click MicrosoftDynamicsAXAif50.

  3. In the adjacent frame, right-click the *.svc file for the relevant service, and then click Browse. A Web browser is displayed for your service.

  4. Verify that the browser shows acceptable information for your service. The display might include C# or Visual Basic code for your Web service.

Headers and IIS Authentication

The IIS mode of authentication must be set to anonymous and to integrated.

NoteNote

The anonymous IIS authentication mode does not always matter for messages that take the default values for most of their <Header> related settings, such as for <SourceEndpointUser>.


The following steps show you how to set the IIS authentication mode by using the Computer Management tool that is provided by the Microsoft Windows operating system.

  1. Click the Windows Start button.

  2. Click My Documents to start Windows Explorer.

  3. Click Folders to display the directory tree view control.

  4. In the Explorer tree view, under Desktop, right-click My Computer, and then click Manage.

  5. Expand Services and Applications, expand Internet Information Services (IIS) Manager, expand Web Sites, expand Default Web Site, right-click MicrosoftDynamicsAxAif50, and then click Properties.

  6. Click the Directory Security tab, and then click Edit in the Authentication and access control section.

  7. Select Enable anonymous access.

Leave the Computer Management window open for the next procedure.

Web.Config wsHttpBinding

If your code must override the default for a header item such as source endpoint user, you must configure your AIF Web site to use the wsHttpBinding binding. The default binding basicHttpBinding does not support calls to AIF Web services where header default values are overridden.

NoteNote

The Microsoft Windows SDK provides a tool that you can use to make the web.config edits.


You can configure the wsHttpBinding binding by editing the web.config file for your AIF Web site.

  1. In the Computer Management window, click the MicrosoftDynamicsAxAif50 node in the tree view.

  2. In the listview on the other pane, right-click the web.config item, click Properties, and then click the ASP.NET tab.

  3. Use an editor application such as Notepad to modify the web.config file at its location shown in the File location text box.

The edits needed in web.config are described next, and are shown in the XML snippet that follows.

  1. Under the <bindings> tag, add a <wsHttpBinding> tag, which includes a child <binding> tag.

  2. In the child <binding> tag, set the name attribute to a unique value, such as wsHttpBindingAuthAif.

  3. In the <service> tag for your service, set the binding attribute to wsHttpBinding.

  4. In the <service> tag for your service, set the bindingConfiguration attribute to wsHttpBindingAuthAif (or the unique name that you chose earlier in the <binding> tag).

TipTip

If you make a binding change to the service in the web.config file after a service reference has already been added to your project, you must also update the binding information in the app.config file. The binding information is contained in the <binding> element.


XML Snippet from Web.Config

The following XML snippet from the web.config file shows the edits to support the wsHttpBinding binding.

<configuration>
...
  <system.serviceModel>

    <bindings>
      <wsHttpBinding>
        <binding name = "wsHttpWindowsAuthAif" />
      </wsHttpBinding>
    </bindings>
...
    <services>
      <service behaviorConfiguration = "serviceBehaviorConfiguration"
        name = "Microsoft.Dynamics.IntegrationFramework.Service.SalesOrderService">
        <endpoint address = "" binding = "wsHttpBinding" bindingConfiguration = "wsHttpWindowsAuthAif"
          bindingNamespace = "http://schemas.microsoft.com/dynamics/2008/01/services"
          contract = "Microsoft.Dynamics.IntegrationFramework.Service.SalesOrderService" />
      </service>
    </services>
...
  </system.serviceModel>
</configuration>

You can use Microsoft Visual Studio 2008 to build a .NET Framework application in C# to call a Web service exposed by AIF.

  1. In Visual Studio, create a new project of type Console Application.

  2. In Solution Explorer, expand the node for your project.

  3. Right-click the References node, and then click Add Service Reference.

  4. In the Address bar, enter the HTTP address for the *.svc file that is listed in IIS Manager for your service.

    NoteNote

    For example, if IIS and Visual Studio are on the same computer, the .svc file address could be the following:

    http://localhost/MicrosoftDynamicsAXAif50/SalesOrderService.svc


  5. Click Go.

  6. The form becomes populated with a node for your service. Click the option button for your service.

  7. In the Namespace field, enter the namespace name that you would like for the proxy C# code that Visual Studio generates.

  8. Click OK.

  9. In Solution Explorer, expand Service References, click the node for the service reference that you created, and then click View in Object Browser.

You are now ready to use the proxy classes in your program.

basicHttpBinding for Visual Studio 2005

Visual Studio 2005 uses the SOAP 1.2 platform for its calls to Web services. SOAP 1.2 supports the basicHttpBinding configuration, but not wsHttpBinding. Therefore, your Visual Studio 2005 compiled C# code should not override message header values such as source endpoint user.

NoteNote

There are SDK downloads available from Microsoft that can add wsHttpBinding support to Visual Studio 2005.


There are several groups of classes (or types) that are frequently needed when a C# application calls an AIF Web service. These groups are identified by their namespace. Some are installed with the .NET Framework. Others can be automatically generated by using Visual Studio 2008.

The following table lists many of the classes that are frequently used by application programs that call AIF Web services. Some of the table entries are specific to the SalesOrderService that is used in the C# code sample that is described elsewhere in this topic.

Namespace

Class

Description

MyProgramNs .MyServiceReferNs

AxdEntity_SalesLine

Has a member for every field in the SalesLine table.

MyProgramNs .MyServiceReferNs

AxdEntity_SalesTable

Has a member for every field in the SalesTable table.

MyProgramNs .MyServiceReferNs

CriteriaElement

Represents one <CriteriaElement> tag under the <QueryCriteria> tag.

MyProgramNs .MyServiceReferNs

Operator

An enum with the value that is used in the <Operator> tag, under <CriteriaElement>.

MyProgramNs .MyServiceReferNs

QueryCriteria

Represents the <QueryCriteria> tag that is used for find service operations.

MyProgramNs .MyServiceReferNs

SalesOrderServiceClient

Has the service methods, such as find and create. Also has members for channel and other items related to the <Header> elements.

System .ServiceModel

EndpointAddress

Used when you want to override the default endpoint value, in the message header.

System .ServiceModel

EndpointAddressBuilder

Builds an instance of EndpointAddress.

System .ServiceModel

IClientChannel

The interface that is implemented by SalesOrderServiceClient.InnerChannel. The InnerChannel is used to override the default for endpoints and other <Header> items.

System .ServiceModel

OperationContext

Has static members for setting message headers.

System .ServiceModel

OperationContextScope

Creates a block within which an OperationContext is in scope.

System .ServiceModel .Channels

AddressHeader

Used to override the default for the endpoint.

System .ServiceModel .Channels

MessageHeader

Used to override the default for the target company.

The following C# code calls an AIF Web service by using the classes that are automatically generated by Visual Studio 2008. The code contains a Main method where the program starts to run. The code calls a method named find. This is similar to the find service that can be listed in the <Action> tag in an XML representation of an inbound message for AIF.

using                      System;
using SysColl            = System.Collections;
using SysSvcmod          = System.ServiceModel;
using SysSvcmodChan      = System.ServiceModel.Channels;
using SysXml             = System.Xml;
// For SalesSalesOrderService in AIF.
// Code in this namespace is automatically generated by Visual Studio.
using AifSos             = AifWebSvcFromCSharp22.ServiceReference1;

namespace AifWebSvcFromCSharp22
{
    class ProgramClass
    {
        protected AifSos.SalesOrderServiceClient
            m_salesOrderServiceClient;


        static void Main(string[] args) // .entrypoint
        {
            ProgramClass                     programClass;
            AifSos.SalesOrderServiceClient   salesOrderServiceClient;

            try
            {
                salesOrderServiceClient =
                    new AifSos.SalesOrderServiceClient();

                programClass = new ProgramClass
                    (salesOrderServiceClient);

                programClass.SendMessage();
            }
            catch (SysSvcmod.FaultException<AifSos.AifFault>
                aifFaultExcepn)
            {
                Console.Out.WriteLine(aifFaultExcepn.Code);
                Console.Out.WriteLine(aifFaultExcepn.ToString());
            }
            catch (Exception excepn)
            {
                Console.Out.WriteLine(excepn.ToString());
            }
        }


        protected ProgramClass // Constructor
            (AifSos.SalesOrderServiceClient salesOrderServiceClient)
        {
            this.m_salesOrderServiceClient = salesOrderServiceClient;
        }


        protected void SendMessage()
        {
            AifSos.QueryCriteria             queryCriteria;
            SysSvcmod.OperationContextScope  operContextScope;

            try
            {
                operContextScope = new SysSvcmod.OperationContextScope
                    (
                    // Implements SysSvcmod.IClientChannel.
                    m_salesOrderServiceClient.InnerChannel
                    );

                // .Dispose is called when the using block ends.
                // After .Dispose, all header related settings
                // are erased, meaning the default values are
                // again in effect.
                using(operContextScope)
                {
                    this.PrepareHeader();

                    queryCriteria = this
                        .PrepareBody_QueryCriteria();

                    this.CallAifSalesOrderService_Find
                        (queryCriteria);
                }
            }
            catch (Exception excepn)
            {
                Console.Out.WriteLine(excepn.ToString());
            }
        }


        protected void PrepareHeader()
        {
            Guid guidMesgId = Guid.NewGuid();
            Console.Out.WriteLine
                ("MessageId = " + guidMesgId.ToString());
            this.SetHeader_MessageId
                (
                guidMesgId
                );
/**** These values are environment dependent.
            this.SetHeader_DestinationEndpoint
                (
                "Lep2Dat"
                );
            this.SetHeader_SourceEndpointUser
                (
                new Uri("urn:NorthwindTraders")
                ,@"myDomain\myLoginName"
                );
*****/
        }


        protected void SetHeader_MessageId
            (Guid guidMessageId)
        {
            SysXml.UniqueId guidUniqueId;

            guidUniqueId = new SysXml.UniqueId(guidMessageId);

            SysSvcmod.OperationContext.Current
                .OutgoingMessageHeaders.MessageId = guidUniqueId;
        }


        protected void SetHeader_SourceEndpointUser
            (
            Uri uriEndpoint
            ,string sEndpointUser
            )
        {
            SysSvcmodChan.AddressHeader       addressHeader;
            SysSvcmod.EndpointAddressBuilder  epAddressBuilder;
            SysSvcmod.EndpointAddress         epAddress1
                                             ,epAddress2;

            addressHeader = SysSvcmodChan.AddressHeader
                .CreateAddressHeader
                    ("SourceEndpointUser"
                    ,"http://schemas.microsoft.com/dynamics/2008/01/services"
                    ,sEndpointUser
                    );
            epAddress1 = new SysSvcmod.EndpointAddress
                (
                uriEndpoint
                ,addressHeader
                );
            epAddressBuilder = new SysSvcmod
                .EndpointAddressBuilder(epAddress1);
            epAddress2 = epAddressBuilder.ToEndpointAddress();

            SysSvcmod.OperationContext.Current
                .OutgoingMessageHeaders.From = epAddress2;
        }


        protected void SetHeader_DestinationEndpoint
            (
            string sDestinationEndpointName
            )
        {
            SysSvcmodChan.MessageHeader messageHeader;

            messageHeader = SysSvcmodChan.MessageHeader
                .CreateHeader
                    (
                    "DestinationEndpoint"
                    ,"http://schemas.microsoft.com/dynamics/2008/01/services"
                    ,sDestinationEndpointName
                    );
            SysSvcmod.OperationContext.Current
                .OutgoingMessageHeaders.Add(messageHeader);
        }


        protected AifSos.QueryCriteria PrepareBody_QueryCriteria()
        {
            AifSos.QueryCriteria         queryCriteria;
            AifSos.CriteriaElement[]     criteriaElements;

            criteriaElements = new AifSos.CriteriaElement[1];
            criteriaElements[0] = new AifSos.CriteriaElement();

            criteriaElements[0].DataSourceName = "SalesTable";
            criteriaElements[0].FieldName = "SalesId";
            criteriaElements[0].Operator = AifSos.Operator.Range;
            criteriaElements[0].Value1 = "00007_036";
            criteriaElements[0].Value2 = "00010_036";

            queryCriteria = new AifSos.QueryCriteria();
            queryCriteria.CriteriaElement = criteriaElements;
            return queryCriteria;
        }


        protected void CallAifSalesOrderService_Find
            (AifSos.QueryCriteria queryCriteria)
        {
            AifSos.AxdSalesOrder         axdSalesOrder;
            AifSos.AxdEntity_SalesTable  axdEntity_SalesTable;
            AifSos.AxdEntity_SalesLine   axdEntity_SalesLine;
            SysColl.IEnumerator          enumerSalesTable
                                        ,enumerSalesLine;
            int iCountLoops1 = 0
                ,iCountLoops2;

            // Issue the Find.
            axdSalesOrder = this.m_salesOrderServiceClient
                .find(queryCriteria);

            // Loop through the results.
            enumerSalesTable = axdSalesOrder.SalesTable
                .GetEnumerator();

            while (enumerSalesTable.MoveNext())
            {
                ++iCountLoops1;

                axdEntity_SalesTable =
                    (AifSos.AxdEntity_SalesTable) // cast
                    enumerSalesTable.Current;

                Console.Out.WriteLine
                    ( Environment.NewLine
                    + "SalesTable["
                    + iCountLoops1
                    + "]: SalesId = "
                    + axdEntity_SalesTable.SalesId
                    + " , CustAccount = "
                    + axdEntity_SalesTable.CustAccount
                    + " , CustGroup = "
                    + axdEntity_SalesTable.CustGroup
                    );

                // Loop through the child rows.
                if (null != axdEntity_SalesTable.SalesLine)
                {
                    enumerSalesLine = axdEntity_SalesTable
                        .SalesLine.GetEnumerator();

                    iCountLoops2 = 0;
                    while (enumerSalesLine.MoveNext())
                    {
                        ++iCountLoops2;

                        axdEntity_SalesLine =
                            (AifSos.AxdEntity_SalesLine) // cast
                            enumerSalesLine.Current;

                        Console.Out.WriteLine
                            (
                            " ** SalesLine["
                            + iCountLoops2
                            + "]: LineAmount = "
                            + axdEntity_SalesLine.LineAmount
                            );
                    } // End loop: SalesLine (child)
                }
            } // End loop: SalesTable (parent)
        }
    }
/******** Actual console output
[C:\MyCsAifProject\]
>> AifWebSvcFromCSharp22.exe
MessageId = 297ce415-2ec6-485c-a168-bf2b157ac817

SalesTable[1]: SalesId = 00007_036 , CustAccount = 4009 , CustGroup = 20
 ** SalesLine[1]: LineAmount = 55.00

SalesTable[2]: SalesId = 00008_036 , CustAccount = 4010 , CustGroup = 20
 ** SalesLine[1]: LineAmount = 165.00
 ** SalesLine[2]: LineAmount = 132.00

SalesTable[3]: SalesId = 00009_036 , CustAccount = 4009 , CustGroup = 20
 ** SalesLine[1]: LineAmount = 192.50

SalesTable[4]: SalesId = 00010_036 , CustAccount = 4000 , CustGroup = 40
 ** SalesLine[1]: LineAmount = 2062.50
 ** SalesLine[2]: LineAmount = 2475.00

[C:\MyCsAifProject\]
>>
********/
}

In addition to the services that ship with Microsoft Dynamics AX, you can create a custom Web service for AIF. Your Web service might accept parameters of the primitive types that are available in X++. Client programs, such as a .NET Framework program coded in C#, have their own data types that represent these same primitive types. For example, a System.Int32 in .NET Framework corresponds to an int in X++.

The system automatically converts values between the corresponding primitive data types of the client and the AIF service. For more information, see AIF Services and Primitive Data Type Conversions for XML and .NET Framework.

In Microsoft Dynamics AX 2009, the default maximum size for an AIF Web service message is 64 KB.

NoteNote

This default size is set by Windows Communication Foundation (WCF) which is used by AIF Web services.


Earlier versions of Microsoft Dynamics AX used .NET Framework Web servicing directly and had a much larger default maximum of 4096 KB.

To increase the maximum message size, you edit the web.config file for your AIF Web site. You can change the values for the following two attributes on the <binding> tag.

maxReceivedMessageSize = "4097001"

maxBufferSize = "4097001"

The previous two attributes are shown in the following partial web.config file.

<configuration>
...
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="wsHttpWindowsAuth"
          maxReceivedMessageSize = "4097001"
          maxBufferSize = "4097001"
        />
      </wsHttpBinding>
    </bindings>
  </system.serviceModel>
...
</configuration>
Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback

Community Additions

ADD
Show:
© 2014 Microsoft. All rights reserved.