Building ERP Solutions with Microsoft Dynamics NAV
上QQ阅读APP看书,第一时间看更新

Creating the consumer application

Let's learn how to create the consumer application by performing the following steps:

  1. In order to create the application that will use our published NAV web service, open Visual Studio, create a new project, and in the New Project window select the Console Application project type:
  2. Give a desired name to your solution (for example, ConsoleApplicationNAV) and click OK.
  3. Visual Studio creates the template for the solution project. You can see it in the Solution Explorer window in the right pane:
  4. Here, the Program.cs file contains the core of the console application (Main) while App.config is the application configuration file, an XML file that contains specific settings for the application.
  5. Now we have to add a reference to our NAV web service in order to use it. To do this, right-click on your solution file and choose Add | Service Reference… as shown in the following screenshot:
  6. Here you can add a reference to one or more Windows Communication Foundation (WCF) services in the current solution, locally, on a local area network or on the Internet.
  7. For NAV, we don't have a WCF service but instead a SOAP XML web service. For adding a reference to an XML web service, in the Add Service Reference window click on Advanced…:
  8. And then click on Add Web Reference…:
  9. In the Add Web Reference window, type the URL of your NAV web service (the SOAP URL you can find in the Microsoft Dynamics NAV Web Service page) and Visual Studio will create a proxy for your web service:
  10. To complete the operation, give a desired web reference name (for example, NAVWS) and click Add Reference.

    Now your solution contains a web reference to your NAV web service:

  11. We're ready to start writing C# code now. The first thing to do is to write a using clause for adding a reference to the NAVWS namespace:
            using ConsoleApplicationNAV.NAVWS; 
    
  12. Console applications have startup parameters that you can specify as arguments in order to take actions (the string[] args parameter in the Main function). In this sample application, we want to read sales orders and create new ones, so we want to have a startup parameter, READ, to read the NAV registered sales orders and CREATE to create a new sales order.
  13. In the Main function, the first thing to do is to check if the number of startup parameters for the console application is correct. If it's not correct, the best thing to do is to print the syntax instructions to the screen:
                        string OperationType; 
                        //If startup parameters are different from one, 
                         write the application syntax on screen and exit 
                        if (args.Length != 1) 
                        { 
                            Console.WriteLine(" Usage:"); 
                            Console.WriteLine(" ConsoleApplicationNAV            
                            <OperationType>");
                            Console.WriteLine(" ------ "); 
                            Console.WriteLine(" OperationType:"); 
                            Console.WriteLine(" READ: reads NAV Sales  
                            Orders"); 
                            Console.WriteLine(" CREATE: create a new Sales 
                            Order on NAV"); 
                            Console.WriteLine(" ------ "); 
                            return; 
                        } 
    
  14. Next, we can read the input parameter and process it accordingly:
                      //Reading the Operation Type parameter 
                      OperationType = args[0].ToUpper();           
     
                        switch(OperationType) 
                        { 
                            case "READ": 
                                ReadNAVSalesOrders(); 
                                 break; 
                            case "CREATE": 
                               CreateNAVSalesOrder(); 
                                break; 
                            default: 
                                Console.WriteLine("Wrong parameter!"); 
                                break; 
                         
                        } 
    
  15. Here, we read the input parameter for our application. If the input parameter is READ, we call the function ReadNAVSalesOrders. If the input parameter is CREATE, we call the function CreateNAVSalesOrder, otherwise an error message is printed:
                    private static void ReadNAVSalesOrders() 
                      { 
                           //Here we have to call our NAV web service 
                           for reading Sales Orders 
                      } 
     
                    private static void CreateNAVSalesOrder() 
                      { 
                          //Here we have to call our NAV web service for  
                          creating a Sales Order 
                      } 
    
  16. Now we have to write the logic for the preceding two core functions.

Reading NAV sales orders

Let's learn how to read NAV sales orders by performing the following steps:

  1. In the ReadNAVSalesOrders function, we have to create an instantiation of the NAV web service and explicitly set the URL for this service:
            SalesOrder_Service ws = new SalesOrder_Service(); 
            ws.Url = "..."; 
    
  2. I recommend to place the web service URL in the <applicationSettings> section in the app.config file and then to read it from there.
  3. To do so, right-click on your project, select Properties, and then select Settings.
  4. Here you can add all the application settings variables you want and these can be loaded at runtime in your application via code.
  5. For our example, we can insert a row like the following screenshot:
  6. Here we have created a setting called NAVWSURL where the type is a string and the value is the URL of our NAV web service.
  7. In app.config, Visual Studio creates this entry:
            <applicationSettings> 
               <ConsoleApplicationNAV.Properties.Settings> 
                  <setting name="NAVWSURL" serializeAs="String"> 
                   <value>   
                       http://192.6.1.37:7047/DynamicsNAV90/WS/
                       CRONUS%20Italia%20S.p.A./Page/SalesOrder
                   </value> 
                  </setting>         
               </ConsoleApplicationNAV.Properties.Settings> 
             </applicationSettings> 
    
  8. For dynamically reading this setting, just use this line of code:
            ws.Url = Properties.Settings.Default.NAVWSURL; 
    
  9. To access the NAV web service, we also need authentication. We can use explicit credentials (impersonate a particular user) or we can use the default credentials of the user that runs the application. In this case, we want the credentials for the running user, so we use this line:
            ws.UseDefaultCredentials = true; 
    
  10. The method for retrieving a set of records from a NAV page web service is called ReadMultiple:
            Entity [] ReadMultiple(Entity_Filter[] filterArray, string  
            bookmarkKey, int setSize) 
    
  11. This method reads a filtered set of records (if filters are applied) and returns an array of entities (objects that represents the page web service). The parameters are as follows:
  12. For our sample application, we want to retrieve all orders for the customer code 10000 (Cannon Group SpA). Accordingly to the ReadMultiple method's definition, we have to define an array of filters to apply for the sales order entity (exposed by the web service) and then call the method itself by passing this filter array.

    The piece of code that does the work is this:

            //Setting filters on the table 
            List<SalesOrder_Filter> filterArray = new    
            List<SalesOrder_Filter>(); 
            SalesOrder_Filter filter = new SalesOrder_Filter(); 
            filter.Field = SalesOrder_Fields.Sell_to_Customer_No; 
            filter.Criteria = "10000"; 
            filterArray.Add(filter); 
     
            //Reading sales orders 
            List<SalesOrder> orderList = 
            ws.ReadMultiple(filterArray.ToArray(), null, 0).ToList(); 
    
  13. We have created a SalesOrder_Filter array with a filter on the NAV field, Sell To Customer No. = 10000, and then we have called the ReadMultiple method of the web service by passing the filter array, NULL as bookmarKey (we want the first page of the recordset) and 0 as setSize (we want the complete result set).
  14. The ReadMultiple method returns a SalesOrder array, so here we have used the .ToList() extension of List<T> in order to directly have a List of SalesOrder objects and loop through it for printing the details.

    The complete function code is as follow:

            private static void ReadNAVSalesOrders() 
            { 
               //Here we have to call our NAV web service for reading Sales    
               Orders 
     
               //Web Service instantiation 
               SalesOrder_Service ws = new SalesOrder_Service(); 
               ws.Url = Properties.Settings.Default.NAVWSURL; 
               ws.UseDefaultCredentials = true; 
     
               //Setting filters on the table 
               List<SalesOrder_Filter> filterArray = new  
               List<SalesOrder_Filter>(); 
               SalesOrder_Filter filter = new SalesOrder_Filter(); 
               filter.Field = SalesOrder_Fields.Sell_to_Customer_No; 
               filter.Criteria = "10000"; 
               filterArray.Add(filter); 
     
               //Reading sales orders 
               List<SalesOrder> orderList = 
               ws.ReadMultiple(filterArray.ToArray(), null, 0).ToList(); 
     
               //Printing the results 
               if (orderList!=null) 
               { 
                    foreach(SalesOrder order in orderList) 
                     { 
                        Console.WriteLine("Order No.: " + order.No); 
                        Console.WriteLine("Order Date: " +   
                        order.Order_Date); 
                        Console.WriteLine("----------------"); 
                     } 
          
                  //Waiting user input to terminate 
                  Console.ReadKey(); 
               } 
            } 
    

Creating a NAV sales order

In the CreateNAVSalesOrder function, we use the NAV page web service for creating a sales order with two lines on NAV. This task requires some steps in order to be completed on NAV:

  1. As a first step, we need to instantiate the NAV web service as previously described:
            SalesOrder_Service ws = new SalesOrder_Service(); 
            ws.Url = Properties.Settings.Default.NAVWSURL; 
            ws.UseDefaultCredentials = true; 
    
  2. Now we have to call the NAV web service in order to create the sales header and having the order header initialized with its order number (here it is exactly like pressing the NEW button in the Sales Order Card page in NAV):
            SalesOrder order = new SalesOrder(); 
            ws.Create(ref order); 
    
  3. For this task, we call the Create method by passing a reference to the SalesOrder object to initialize:
            void Create(ref Entity entity) 
    
  4. After this first call, the SalesOrder object is created and we have the order number from NAV.
  5. Now we can update the sales header with all the details and we can initialize the sales lines:
            //Update the Sales Header with details 
            order.Sell_to_Customer_No = "10000"; 
            order.Order_Date = DateTime.Now; 
     
            //Create the Sales Lines array and initialize the lines 
            order.SalesLines = new Sales_Order_Line[2]; 
            for (int i=0; i<2; i++) 
            { 
                order.SalesLines[i] = new Sales_Order_Line(); 
            } 
     
            ws.Update(ref order); 
    
  6. After that we can create the lines:
            //First line 
            Sales_Order_Line line = order.SalesLines[0]; 
            line.Type = NAVWS.Type.Item; 
            line.No = "1000"; 
            line.Quantity = 5; 
            //Second line 
            line = order.SalesLines[1]; 
            line.Type = NAVWS.Type.Item; 
            line.No = "1001"; 
            line.Quantity = 10; 
    
  7. At the end we can update the order lines:
            ws.Update(ref order); 
    
  8. The complete function code is as follows:
            private static void CreateNAVSalesOrder() 
            { 
              //Here we have to call our NAV web service for creating a      
              Sales Order 
     
              //Web Service instantiation 
              SalesOrder_Service ws = new SalesOrder_Service(); 
              ws.Url = Properties.Settings.Default.NAVWSURL; 
              ws.UseDefaultCredentials = true; 
     
              //Create the Sales Header 
              SalesOrder order = new SalesOrder(); 
              ws.Create(ref order); 
     
              //Here the Sales Order is created and we have the order No. 
     
     
              //Update the Sales Header with details 
              order.Sell_to_Customer_No = "10000"; 
              order.Order_Date = DateTime.Now; 
     
              //Create the Sales Lines array and initialize the lines 
              order.SalesLines = new Sales_Order_Line[2]; 
              for (int i=0; i<2; i++) 
               { 
                  order.SalesLines[i] = new Sales_Order_Line(); 
               } 
     
              ws.Update(ref order); 
               
              //First line 
              //Sales_Order_Line line = new Sales_Order_Line(); 
              Sales_Order_Line line = order.SalesLines[0]; 
              line.Type = NAVWS.Type.Item; 
              line.No = "1000"; 
              line.Quantity = 5; 
                 
              //Second line 
              line = order.SalesLines[1]; 
              line.Type = NAVWS.Type.Item; 
              line.No = "1001"; 
              line.Quantity = 10; 
               
                
              //Update the order lines with all the informations 
              ws.Update(ref order); 
     
              Console.WriteLine("Order {0} created successfully.", 
              order.No); 
     
            } 
    
    Tip

    All this code does not contain error handling functions, but you need ALWAYS to enclose every call in a TRY…CATCH block and handling exceptions accordingly.