[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操作更新數據由於有它特殊的地方,會放在單獨的一篇文章中討論。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM