在這篇文章我們將通過文檔服務來創建、讀取銷售訂單等來演示如何使用文檔服務。
實例一:在這個例子中我們使用文件系統適配器端口,通過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操作更新數據由於有它特殊的地方,會放在單獨的一篇文章中討論。