Sunday, October 17, 2010

Building a web service client with WCF

[WCF client for a Spring Webservice: An interoperabilty story. Part 4.]
 
    Building web services and clients are made easier than any time before with Windows Communication Foundation ( WCF ). WCF has reduced the complexity of building web services tremendously. The developer doesn't need to know much number of technologies for related functionality now, as the comprehensive WCF API, with its tools covers them all under a single umbrella.

Technocrati token: 46V7CEXW9ESS
   This post describes the steps involved in building a web service client using WCF. The client program is built as a Windows Forms Application, which invokes the two operations of the Web service which was developed using Spring Web Services Technology in the part 2 of this series[WCF client for a Spring Web service: An interoperability story].

  As I was new to WCF, I expected a big learning curve in understanding the framework, but its well structured API and the comprehensive documentation provided by MSDN ( Micorsoft Developer Network ) helped me to catch up the technology much earlier than expected.

  Initially I started with the command line tools for a thorough understanding, later I found the IDE, Visual C# Express Edition equally useful. Its nice wizards allow us to build the web service client in a matter of minutes.

  I used  Microsoft Visual C# 2010 Express for the development. Here are the steps I have followed for building the web service client.

  1. Create New Project, Windows Forms Application, name it - LiveRestaurantClient.



  2.  Create a new Windows Form (or rename the default Form1), OrderForm.

  3. Add two buttons, with texts, Place Order and Cancel Order, each corresponding to the web service operations that needed to be invoked. Name them, btnPlaceOrder and btnCancelOrder respectively, in the Properties editor.

  4. Add TextBox named txtResult, with a Label, Result:. Now the form looks like this figure.


  5. Make sure your web service running [Start the Web Application, LiveRestaurant, from Eclipse, check the URL of the WSDL is working].

  6. Right click the project, Add Service Reference, provide the URL of the Web Service [http://localhost:8080/LiveRestaurant/spring-ws/OrderService.wsdl], click Go. You should be able to see the service and operations listed as below.


  7. Click OK, now your project has enough components to act as a Client for the LiveRestaurant Web Service. See the project structure now, you can notice the app.config, the configuration file generated, along with the Service Reference artifacts and the required library references, such as System.ServiceModel. Your Solution Explorer now looks like as below.


  8. Modify the app.config, replace the endpoint address [/configuration/system.serviceModel/client/endpoint/@address] with http://localhost:8080/LiveRestaurant/spring-ws/OrderService. Now the app.config should look like this.
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
       <system.serviceModel>
           <bindings>
               <basicHttpBinding>
                   <binding name="OrderServiceSoap11" closeTimeout="00:01:00" openTimeout="00:01:00"
                       receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
                       bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
                       maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                       messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
                       useDefaultWebProxy="true">
                       <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
                           maxBytesPerRead="4096" maxNameTableCharCount="16384" />
                       <security mode="None">
                           <transport clientCredentialType="None" proxyCredentialType="None"
                               realm="" />
                           <message clientCredentialType="UserName" algorithmSuite="Default" />
                       </security>
                   </binding>
               </basicHttpBinding>
           </bindings>
         <!--<client>
           <endpoint address="http://www.liverestaurant.com/spring-ws/OrderService/"
               binding="basicHttpBinding" bindingConfiguration="OrderServiceSoap11"
               contract="LiveRestaurant.OrderService" name="OrderServiceSoap11" />
         </client>-->
         <client>
           <endpoint address="http://localhost:8080/LiveRestaurant/spring-ws/OrderService"
               binding="basicHttpBinding" bindingConfiguration="OrderServiceSoap11"
               contract="LiveRestaurant.OrderService" name="OrderServiceSoap11" />
         </client>
       </system.serviceModel>
    </configuration>
    App.config
  9. Take a look at Reference.cs and see if you can locate the Client class, OrderServiceClient, with all required methods for you to invoke the service.
  10. Add event handler methods to both the buttons, btnPlaceOrder and btnCancelOrder to invoke the service operations, placeOrder and cancelOrder respectively. Either you double click the buttons in Design mode, and write the invocation code yourself in the generated event(btnPlaceOrder_Click and btnCancelOrder_Click) methods,

    OR

    Copy paste the following code in the OrderForm.cs


    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;

    using LiveRestaurantClient.LiveRestaurant;

    namespace LiveRestaurantClient
    {
       public partial class OrderForm : Form
       {
           public OrderForm()
           {
               InitializeComponent();
           }

           private void btnPlaceOrder_Click(object sender, EventArgs e)
           {

               OrderServiceClient client = new OrderServiceClient();

               this.textResult.Text = "Preparing a dummy Order....";

               placeOrderRequest request = new placeOrderRequest();
               request.order = prepareDummyOrder();

               this.textResult.Text += "\r\n\r\nPlacing the Order....";

               placeOrderResponse response = null;
               try
               {
                   response = client.placeOrder(request);

                   String orderRefNo = response.refNumber;

                   this.textResult.Text += "\r\n\r\nOrder has been placed successfully, Reference No: " + orderRefNo;
               }
               catch (Exception ex)
               {
                   this.textResult.Text += "\r\n\r\nException while invoking OrderService, Message: " + ex.Message;
                   this.textResult.Text += "\r\n\r\n================= Stack Trace ======================";
                   this.textResult.Text += "\r\n\r\n" + ex.StackTrace;
               }


           }

           private Order prepareDummyOrder()
           {
               Order order = new Order();

               order.customer = prepareCustomer();
               order.dateSubmitted = new DateTime(2010, 10, 15, 08, 00, 00);
               order.orderDate = new DateTime(2010, 10, 15, 12, 00, 00);
               order.items = prepareOrderItems();
               
               return order;
           }

           private FoodItem[] prepareOrderItems()
           {
               FoodItem[] items = new FoodItem[5];

               items[0] = prepareFoodItem("Vegetable Thali", FoodItemType.Meals, 2);
               items[1] = prepareFoodItem("Kheer/ Palpayasam", FoodItemType.Desserts, 4);
               items[2] = prepareFoodItem("Fresh Orange Juice", FoodItemType.Juices, 1);
               items[3] = prepareFoodItem("Fresh Carrot Juice", FoodItemType.Juices, 1);
               items[4] = prepareFoodItem("Sweet Corn Soup", FoodItemType.Starters, 2);

               return items;
           }

           private FoodItem prepareFoodItem(String name, FoodItemType type, double quantity)
           {
               FoodItem item = new FoodItem();
               item.name = name;
               item.type = type;
               item.quantity = quantity;
               return item;
           }



           private Customer prepareCustomer()
           {
               Customer customer = new Customer();

               customer.name = prepareCustomerName();

               customer.addressPrimary = prepareAddress("123",
                   "My Office Building", "My Office Street",
                   "Dubai", "United Arab Emirates",
                   "0097150xxxxxxx", "009714xxxxxxx",
                   "shameer@mycompany.com");

               customer.addressSecondary = prepareAddress("234",
                   "My Home Building", "My Home Street",
                   "Dubai", "United Arab Emirates",
                   "0097150xxxxxxx", "009714xxxxxxx",
                   "shameer@myhome.com");

               return customer;
           }

           private Name prepareCustomerName()
           {
               Name name = new Name();
               
               name.lName = "Shameer";
               name.fName = "Kunjumohamed";

               return name;
           }

           private Address prepareAddress(String doorNo, String building, String street, String city, String country, String phoneMobile, String phoneLandline, String email)
           {
               Address address = new Address();
               address.doorNo = doorNo;
               address.building = building;
               address.street = street;
               address.city = city;
               address.country = country;
               address.phoneMobile = phoneMobile;
               address.phoneLandLine = phoneLandline;
               address.email = email;

               return address;
           }

           private void btnCancelOrder_Click(object sender, EventArgs e)
           {
               cancelOrderRequest request = new cancelOrderRequest();
               request.refNumber = "Ref-2010-9-15-0.8432452204897198";
               OrderServiceClient client = new OrderServiceClient();

               this.textResult.Text = "Cancelling Order [" + request.refNumber + "]...........";

               cancelOrderResponse response = null;
               try
               {
                   response = client.cancelOrder(request);

                   if(response.cancelled)
                       this.textResult.Text += "\r\n\r\nOrder has been cancelled successfully.";
                   else
                       this.textResult.Text += "\r\n\r\nOrder is not cancelled successfully.";
               }
               catch (Exception ex)
               {
                   this.textResult.Text += "\r\n\r\nException while invoking OrderService, Message: " + ex.Message;
                   this.textResult.Text += "\r\n\r\n================= Stack Trace ======================";
                   this.textResult.Text += "\r\n\r\n" + ex.StackTrace;
               }
           }
       }
    }

    OrderForm.cs

  11. Now the application is ready to kick off, run the application from the IDE, pressing F5, or running the default program, Program.cs which starts the OrderForm from the Main method. Click button, Place Order, see the service invoked and the response received. Try the other operation, Cancel Order and see if it working. You can check the Eclipse console to see the service log messages which says, "Order has been placed. Order Info is : com.live.order.domain.Order@1de6817".




  12. You may check the WCF message log file which logs the incoming and outgoing SOAP messages using the WCF Service Trace Viewer Tool ( ScvTraceViewer.exe ). See http://msdn.microsoft.com/en-us/library/ms732023.aspx for more details on SvcTraceViewer.exe.

    Message logging is configured in the app.config under section system.diagnostics. The log file is currently configured to generate at C:\logs\LiveRestaurant.svclog. However, I could not get the program create the folder logs automatically, I created it myself later and then the file got generated automatically. I found this logging facility very helpful in debugging and fixing bugs.
   Now our client program is completely functional, the basic communication between the WCF client and the Spring Web service is established. Now we are set to go for more serious levels, such as adding security at both ends.

   Before that, I think it would be nice to build a similar client program in Java using Spring-WS itself, it would help the security features get started easily, serving as a quick test case. Let the next post be about Building Web Service Client using Spring-WS.

    No comments:

    Post a Comment