• [AX]AX2012 AIF(四):文档服务应用实例


    在这篇文章我们将通过文档服务来创建、读取销售订单等来演示如何使用文档服务。

    实例一:在这个例子中我们使用文件系统适配器端口,通过XML文档创建销售订单。首先在Inboud ports创建一个文件适配器的增强型端口,选择一个网络共享目录作为URI(我的配置\\dax\AIFData\AIFIn),注意不要使用本地目录,否则会提示找不到相应目录的错误,此外设置目录的权限允许AOS服务账号读写。在适配器“config”窗口中选择一个用户作为“User default for Administration group”,文件系统适配器将文件的owner作为发送消息的用户,在启用UAC的系统上文件的Owner可能会被设置为管理员组因而无法判断具体是谁创建了XML文档,因此这里选择一个用户作为这些文档的默认Owner。另外我们勾选“Response address”,同样设置为文件系统适配器,选择一个网络共享目录为输出目录(我的配置\\dax\AIFData\AIFOut)。在Service operations我们选择 SalesSalesOrderService.create、SalesSalesOrderService.read、SalesSalesOrderService.findKeys操作,在“Data policies”中激活所有的字段。其他配置看自己的需求配置,最后激活这个端口。

    下面要做的就是准备好创建销售订单的消息XML,下面是一个样例:

    <?xml version="1.0" encoding="utf-8" ?>
    <Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
      <Header>
        <MessageId>{5603D03A-4380-404D-9F27-738BE0FEA13E}</MessageId>
        <Action>http://schemas.microsoft.com/dynamics/2008/01/services/SalesOrderService/create</Action>
      </Header>
      <Body>
        <MessageParts>
          <SalesOrder xmlns="http://schemas.microsoft.com/dynamics/2008/01/documents/SalesOrder">
            <SalesTable class="entity">
              <CustAccount>9001</CustAccount>
              <DeliveryDate>2013-03-11</DeliveryDate>
              <PurchOrderFormNum>PO</PurchOrderFormNum>
              <ReceiptDateRequested>2013-02-11</ReceiptDateRequested>
              <SalesLine class="entity">
                <ItemId>1206</ItemId>
                <SalesQty>123</SalesQty>
                <SalesUnit>ea</SalesUnit>
              </SalesLine>
            </SalesTable>
          </SalesOrder>
        </MessageParts>
      </Body>
    </Envelope>

    注意消息头中<Action>中我们用的SalesOrderService/create请求,将这个XML保存(文件名so_create_01.xml)到入站目录\\dax\AIFData\AIFIn,这个时候什么都不会发生,我们还缺少一个Batch job来运行AifGatewayReceiveService, AifGatewaySendService, AifInboundProcessingService, 和AifOutboundProcessingService这个几个服务,如果觉得麻烦用下面的Job手工执行一次吧:

    static void AifProcessingClasses(Args _args)
    {
     AifGatewayReceiveService receive = new AifGatewayReceiveService();
     AifInboundProcessingService inbound = new AifinboundProcessingService();
     AifOutboundProcessingService outbound = new AifOutboundProcessingService();
     AifGatewaySendService send = new AifGatewaySendService();
    
    receive.run();
    inbound.run();
    outbound.run();
    send.run();
    }

    一切正常的话你会发现so_create_01.xml消失,在\\dax\AIFData\AIFOut会多出来一个xml,这就是新创建销售订单的响应结果,形如:

    <?xml version="1.0" encoding="UTF-8"?>
    <Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
      <Header>
        <MessageId>{D630C246-3C62-42AE-BE69-4BFE609E8470}</MessageId>
        <Action>http://schemas.microsoft.com/dynamics/2008/01/services/SalesOrderService/create</Action>
        <RequestMessageId>{5603D03A-4380-404D-9F27-738BE0FEA13E}</RequestMessageId>
      </Header>
      <Body>
        <MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
          <EntityKeyList xmlns="http://schemas.microsoft.com/dynamics/2006/02/documents/EntityKeyList">
            <EntityKey xmlns="http://schemas.microsoft.com/dynamics/2006/02/documents/EntityKey">
              <KeyData>
                <KeyField>
                  <Field>SalesId</Field>
                  <Value>00000009_050</Value>
                </KeyField>
              </KeyData>
            </EntityKey>
          </EntityKeyList>
        </MessageParts>
      </Body>
    </Envelope>

    在AR下的销售订单列表中你也能看到这个新创建的销售订单。

    实例二:这个例子中我们通过销售订单号来读取订单的完整信息,使用例一中的端口配置。需要更改的是我们的XML消息请求:

    <?xml version="1.0" encoding="UTF-8"?>
    <Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
      <Header>
        <MessageId>{D630C246-3C62-42AE-BE69-4BFE609E8470}</MessageId>
        <Action>http://schemas.microsoft.com/dynamics/2008/01/services/SalesOrderService/read</Action>
        <RequestMessageId>{5603D03A-4380-404D-9F27-738BE0FEA13E}</RequestMessageId>
      </Header>
      <Body>
        <MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
          <EntityKeyList xmlns="http://schemas.microsoft.com/dynamics/2006/02/documents/EntityKeyList">
            <EntityKey xmlns="http://schemas.microsoft.com/dynamics/2006/02/documents/EntityKey">
              <KeyData>
                <KeyField>
                  <Field>SalesId</Field>
                  <Value>00000009_050</Value>
                </KeyField>
              </KeyData>
            </EntityKey>
          </EntityKeyList>
        </MessageParts>
      </Body>
    </Envelope>

    其实就是把例一中的响应消息中的Action换成read,同样保存到\\dax\AIFData\AIFIn,运行一次服务JOB,在响应目录中会找到订单详细信息的XML,包含订单头及订单行的所有信息,内容比较长就不列出了。

    实例三:在这个例子中我们使用MSMQ适配器端口,如何部署AIF消息队列参见http://msdn.microsoft.com/EN-US/library/aa834340.aspx。创建MSMQ适配器一个入站端口,使用例一中销售订单服务的read和create两个操作,具体步骤不做介绍。消息队列不像文件夹那样可以直接放入XML文档,下面我们使用C#程序向队列投递消息来创建销售订单:

    static void Main(string[] args)
    {
      
        // The queue name.
        // Replace this AOS name and queue name with the values from 
        // the URI field in the Inbound ports form. 
        // For this walkthrough, 
        // only the server name should be different.
        String QName = "FormatName:DIRECT=OS:DAX\\CreateSO";
        // The path to the sales order XML file
        String XMLPath = "c:\\so_create_01.xml";
    
        // Create the XML document object.
        XmlDocument doc = new XmlDocument();
        doc.Load(XMLPath);
    
        // Create a new message.
        Message msg = new Message();
    
        // Add authentication.
        msg.AttachSenderId = true;
        msg.UseAuthentication = true;
        msg.HashAlgorithm = HashAlgorithm.Sha;
    
        // Attach the document to the message.
        msg.Body = doc;    
    
        // Create the queue object.
        MessageQueue myQ = new MessageQueue(QName);
    
        try
        {
            // Send a message to the queue
            // Create a transaction.
            MessageQueueTransaction myTransaction = new MessageQueueTransaction();
    
            // Begin the transaction
            myTransaction.Begin();
    
            // Send the message
            myQ.Send(msg, "Sales Order", myTransaction);
    
            // End the transaction
            myTransaction.Commit();
        }
        catch (Exception e)
        {
            // Display the description of the exception
            Console.WriteLine(e.Message);
        }  
    
        Console.Write("Done. Press ENTER to continue.");
        Console.In.ReadLine();
    }

    程序比较简单,不多讨论。

    实例四:在这个例子我们使用C#程序通过NetTcp适配器入站端口读取销售信息,如何配置NetTcp端口也从略,创建好一个C#工程,添加服务引用http://DAX:8101/DynamicsAx/Services/SalesOrderRead,主程序:

    static void Main(string[] args)
    {
        // Create the sales order objects
        // Service client
        var cl = new ServiceReference1.SalesOrderServiceClient();
        // Sales order object to receive response
        TCP_Client.ServiceReference1.AxdSalesOrder resp;
    
        // Create the entity key list for the request
        var readRespKeys = new ServiceReference1.EntityKey[1];
        readRespKeys[0] = new ServiceReference1.EntityKey();
        readRespKeys[0].KeyData = new ServiceReference1.KeyField[1];
        readRespKeys[0].KeyData[0] = new ServiceReference1.KeyField();
        readRespKeys[0].KeyData[0].Field = "SalesId";
        readRespKeys[0].KeyData[0].Value = "00000003_050";
    
        try
        {
            // Try to read the sales order
            resp = cl.read(null, readRespKeys);
    
            // Display the information from the first sales table
            Console.WriteLine("For sales order: " + resp.SalesTable[0].SalesId);
            Console.WriteLine("Customer Account is: " + resp.SalesTable[0].CustAccount);
        }
        catch (Exception e)
        {
            Console.WriteLine("Exception: " + e.Message);
            cl.Abort();
        }            
        cl.Close();
    }

    程序读取打印订单00000003_050的客户号,也是比较简单,不多讨论。需要讨论的是上面代码中没有用到的CallContext类,它有Company、LogonAsUser、Language、PropertyBag、MessageId、AX2012 R2引入的PartitionKey几个属性,默认情况下调用服务是以当前进程用户的默认公司执行,使用CallContext则可以设置这些选项,比如:

                var context = new CallContext();
                context.Company = "dat";
                context.LogonAsUser = "yourdomain\userid";
                context.Language = "en-us";

    在调用服务时指定context,比如上面的resp = cl.read(context, readRespKeys),它产生的结果类似XML消息的消息头中指定的相关选项:

    <Header>
        <MessageId>MessageId1</MessageId>
        <LogonAsUser>domain\user1</LogonAsUser>
        <PartitionKey>PartitionKey1</PartitionKey>
        <Company>Company1</Company>
        <Action>create</Action>
    
      </Header>

    实例五这个例子我们使用C#通过HTTP适配器入站端口读取销售订单,HTTP适配器需要将Web service部署到IIS。在C#中使用这类适配器和使用NetTcp适配器端口一样,WSDL地址可能是http://DAX/MicrosoftDynamicsAXAif60/WebSalesOrderRead/xppservice.svc,调用服务的代码和NetTcp一样不用改动,不同的是添加Service reference时app.config中WCF服务绑定端口不一样了,所以这里就不再贴出代码了。

    实例六:这是一个使用C#通过NetTcp或者HTTP适配器端口创建销售订单的例子:

                SalesOrderServiceClient proxy = new SalesOrderServiceClient();
                CallContext context = new CallContext();
                context.Company = "ceu";
    
                AxdSalesOrder salesOrder = new AxdSalesOrder();
                AxdEntity_SalesTable[] salesTables = new AxdEntity_SalesTable[1];
                AxdEntity_SalesTable salesTable = new AxdEntity_SalesTable();
    
    
                salesTable.CurrencyCode = "USD";
                salesTable.CustAccount = "1103";
                salesTable.ReceiptDateRequested = Convert.ToDateTime("2/1/2012");
                salesTable.Payment = "N060";
                salesTable.PurchOrderFormNum = "PO113";
    
    
                AxdType_DimensionAttributeValue dimBusinessUnit = new AxdType_DimensionAttributeValue();
                dimBusinessUnit.Name = "BusinessUnit";
                dimBusinessUnit.Value = "20";
    
                AxdType_DimensionAttributeValue dimCustomerGroup = new AxdType_DimensionAttributeValue();
                dimCustomerGroup.Name = "CustomerGroup";
                dimCustomerGroup.Value = "10";
    
    
                AxdType_DimensionAttributeValue dimDepartment = new AxdType_DimensionAttributeValue();
                dimDepartment.Name = "Department";
                dimDepartment.Value = "500";
    
    
                AxdType_DimensionAttributeValueSet valueSet = new AxdType_DimensionAttributeValueSet();
    
                valueSet.Values = new AxdType_DimensionAttributeValue[3] { dimBusinessUnit, dimCustomerGroup, dimDepartment };
                salesTable.DefaultDimension = valueSet;
    
    
                AxdEntity_SalesLine salesLine = new AxdEntity_SalesLine();
    
                salesLine.ItemId = "1000";
                salesLine.SalesQty = 1;
                salesLine.SalesUnit = "ea";
    
    
                AxdEntity_SalesLine salesLine2 = new AxdEntity_SalesLine();
    
                salesLine2.ItemId = "1000";
                salesLine2.SalesQty = 55;
                salesLine2.SalesUnit = "ea";
    
    
                AxdEntity_SalesLine salesLine3 = new AxdEntity_SalesLine();
                salesLine3.ItemId = "10004";
                salesLine3.SalesQty = 21;
                salesLine3.SalesUnit = "Pcs";
    
    
                AxdEntity_InventDim inventDim = new AxdEntity_InventDim();
                inventDim.InventSiteId = "1";
                salesLine3.InventDim = new AxdEntity_InventDim[1] { inventDim };
    
    
                salesTable.SalesLine = new AxdEntity_SalesLine[3] { salesLine, salesLine2, salesLine3 };
                salesOrder.SalesTable = new AxdEntity_SalesTable[1] { salesTable };
    
                try
                {
    
                    proxy.create(context, salesOrder);
                    Console.WriteLine("Worked");
                }
    
    
                catch (Exception e)
                {
                    throw e;
                }

     实例七:使用findKeys操作查找销售订单文档键值,使用例一中的文件系统适配器入站端口,和创建销售订单的不同点就在于XML消息中的QueryCriteria部分:

    <?xml version="1.0" encoding="UTF-8"?>
    <Envelope xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
      <Header>
        <MessageId></MessageId>
        <Action>http://schemas.microsoft.com/dynamics/2008/01/services/SalesOrderService/findKeys</Action>
      </Header>
      <Body>
        <MessageParts xmlns="http://schemas.microsoft.com/dynamics/2011/01/documents/Message">
          <QueryCriteria xmlns = "http://schemas.microsoft.com/dynamics/2006/02/documents/QueryCriteria">
            <CriteriaElement>
              <DataSourceName>SalesTable</DataSourceName>
              <FieldName>CustAccount</FieldName>
              <Operator>Equal</Operator>
              <Value1>80012</Value1>
            </CriteriaElement>
          </QueryCriteria>
        </MessageParts>
      </Body>
    </Envelope>

    这里查找客户号为80012的所有销售订单,返回这些销售订单的订单号列表,结果就不再列出。如何使用QueryCriteria可以参见http://msdn.microsoft.com/EN-US/library/aa892862.aspx,更多如何创建服务操作XML消息参见http://msdn.microsoft.com/EN-US/library/jj191598.aspx

    以上例子中演示了创建、读取销售订单,其他的服务操作雷同不多讨论,使用update操作更新数据由于有它特殊的地方,会放在单独的一篇文章中讨论。

      

  • 相关阅读:
    我的ORM之八-- 事件
    JavaScript(四):函数
    JavaScript(三):数据类型转换
    CSS(九):设置盒子水平垂直居中
    CSS(八):定位属性
    CSS(三):引入样式和优先级
    Dapper:安装Dapper时报错
    HTML(四):行级标签和块级标签
    解决Linux里面未启用网卡的问题
    linq操作符:分区操作符
  • 原文地址:https://www.cnblogs.com/duanshuiliu/p/2886891.html
Copyright © 2020-2023  润新知