WSE 2.0 Messaging

Document Sample
WSE 2.0 Messaging Powered By Docstoc
					Hands-On Lab Manual: WSE 2.0 Messaging




                      TechEd 2003
                       HOL-WEB01


              WSE 2.0 Messaging
                Hands-On Lab Manual


                        Aaron Skonnard
Hands-On Lab Manual: WSE 2.0 Messaging


Contents
Contents .........................................................................................................ii
Introduction ................................................................................................... 3
     Purpose........................................................................................................................... 3
     Prerequisites.................................................................................................................... 3
     Lab Overview ................................................................................................................... 3
     Getting Help .................................................................................................................... 3
     Note ............................................................................................................................... 3
Exercises ....................................................................................................... 4
        A.    One-Way Messaging................................................................................................ 4
         1.     Getting Started ................................................................................................... 4
         2.     Implementing a SoapReceiver ............................................................................... 4
         3.     Configuring MathReceiver ..................................................................................... 5
         4.     Sending Messages to the SoapReceiver .................................................................. 6
         5.     Supporting Multiple Operations.............................................................................. 7
        B.    Request/Response Messaging ................................................................................... 8
         1.     Getting Started ................................................................................................... 8
         2.     Implementing a Response Receiver ........................................................................ 8
         3.     Configuring MathResponseReceiver ........................................................................ 9
         4.     Specifying a Reply Address ................................................................................. 10
         5.     Sending a Response Message .............................................................................. 10
        C.    Higher-Level Messaging ......................................................................................... 11
         1.     Getting Started ................................................................................................. 11
         2.     Implementing a SoapService............................................................................... 11
         3.     Configuring MathService ..................................................................................... 13
         4.     Implementing a SoapClient ................................................................................. 13
         5.     Using a SoapClient ............................................................................................ 14
        D.    Using TCP ............................................................................................................ 14
         1.     Getting Started ................................................................................................. 14
         2.     Using TCP to Send/Receive Messages ................................................................... 15
         3.     Tracing TCP Messages ........................................................................................ 15
        E.    Using HTTP .......................................................................................................... 17
         1.     Getting Started ................................................................................................. 17
         2.     Configuring SoapReceivers in ASP.NET ................................................................. 17
         3.     Creating a Virtual Directory................................................................................. 18
         4.     Running the Client ............................................................................................. 20
         5.     Tracing HTTP Messages ...................................................................................... 20
        F.    WSE2 Chat Program (Time Permitting) .................................................................... 20
         1.     Getting Started ................................................................................................. 21
         2.     Implementing WseChat ...................................................................................... 21
Summary ......................................................................................................21




ii
Hands-On Lab Manual: WSE 2.0 Messaging

Introduction
Purpose
This lab will help you understand WSE 2.0's fundamental messaging API including how to send and
receive messages over different transports using a variety of message exchange patterns (MEPs).

Prerequisites
This lab was designed for developers already familiar with Microsoft .NET, XML and Web services
technologies. Specifically, you should have some experience working with:

       •   C# and Visual Studio.NET

       •   XML 1.0, Namespaces, and SOAP Messages

       •   System.Xml APIs (e.g., DOM, XPath, etc.)

       •   HTTP Pipeline (e.g., IHttpHandler, web.config, etc.)

Lab Overview
The lab is organized into several directories, each of which contains information to assist you in
completing the exercises.

HOL-WEB01                                   Lab Module
   |
   |-Manual                                 Lab Manual
   |
   |-Exercises                              Exercise Source Files


The Manual directory provides detailed procedures that guide you through the process of completing
the exercises while the Exercises directory contains the "before" and "after" Visual Studio.NET
projects.

Getting Help
If you get stuck on a particular exercise you can a) find a lab proctor to assist you (proctors are
available during lab hours), b) self-diagnose the issue by peaking at the solution project in the
Exercises\After directory.



Note
The working directory for this lab is C:\Labs\HOL-WEB01. Use this as the reference point for all
instructions on this lab.




3
Hands-On Lab Manual: WSE 2.0 Messaging

Exercises
Walk through each exercise following the detailed step-by-step instructions. You'll be working in the
Exercises\Before directory.

    A. One-Way Messaging
    WSE 2.0's messaging API is built on two core classes found: SoapSender and SoapReceiver.
    You use these classes to send and receive SOAP envelopes respectively. A SOAP envelope is
    modeled by the SoapEnvelope class.

    Your first exercise is to finish building an application that uses SoapSender and SoapReceiver to
    exchange SOAP envelopes between components in-process. If you get stuck along the way, feel
    free to check out the solution found in Exercises\After.

    1. Getting Started
    •   Open the MessagingOneWay project found in Exercises\Before.
    •   Familiarize yourself with the form and the skeleton code. As you can see, the purpose of the
        application is to perform mathematical operations on a few numbers. You're going to
        accomplish this by implementing a SoapReceiver. Then, when the user clicks one of the math
        buttons, you'll use a SoapSender object to send a message to your SoapReceiver.
    •   Add a reference to the Microsoft.Web.Services assembly (go to Project | Add Reference,
        scroll down, and select Microsoft.Web.Services).
    •   Open Form1.cs and add the following using statements:

           using Microsoft.Web.Services;
           using Microsoft.Web.Services.Messaging;
           ...

    •   You'll be working in Form1.cs for the remainder of the exercise.

    2. Implementing a SoapReceiver
    •   Define a new class called MathReceiver that derives from SoapReceiver (do this below the
        Form1 class definition towards the bottom of the file). Add a public field called SenderForm of
        type Form1 to your new class. The client will have to initialize this before sending messages so
        the receiver can write the results back to the form.
    •   The following code fragment illustrates what the class should look like:

           namespace MessagingSample
           {
               ... // Form1 class definition
               public class MathReceiver : SoapReceiver
               {
                     // reference to the sender's form
                     public Form1 SenderForm;
                       ... // implement MathReceiver here
               }
           }

•   Within MathReceiver, override the Receive method as illustrated below. Note: you can use
    Visual Studio.NET's Class View to override the method. Navigate to the Receive method, right
    click, and select Add | Override.

           ...
           public class MathReceiver : SoapReceiver
           {
4
Hands-On Lab Manual: WSE 2.0 Messaging

                 // reference to the sender's form
                 public Form1 SenderForm;
                 protected override void Receive(SoapEnvelope e)
                 {
                       ... // implement Receive here
                 }
           }
           ...

•   Receive is where you do the work to process the incoming SOAP message. For now, assume that
    the SOAP message is going to look like this:

           <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
              <s:Body>
                 <x:add xmlns:x='urn:math'>
                    <x>33</x>
                    <y>66</y>
                 </x:add>
              </s:Body>
           </s:Envelope>

•   Finish implementing Receive to process the message. The SoapEnvelope class exposes the
    SOAP envelope as a customized DOM tree that includes XPath support (via SelectNodes and
    SelectSingleNode). Use XPath to extract the x and y values as shown here:

           ...
           public class MathReceiver : SoapReceiver
           {
               // reference to the sender's form
               public Form1 SenderForm;
                 protected override void Receive(SoapEnvelope e)
                 {
                    // extract x and y values from incoming SOAP message
                    double x = XmlConvert.ToDouble(
                        e.SelectSingleNode("//x").InnerText);
                    double y = XmlConvert.ToDouble(
                        e.SelectSingleNode("//y").InnerText);
                    double result = x+y;
                     ... // do something with result
                 }
           }
           ...

•   We need to do something with the result. In this case, we don't have anywhere to send a response
    (because it was a one-way message without a reply address). Assuming the client sets the
    SenderForm field ahead of time, you can write the result directly to the ResultBox text box
    (This should be added at the end of the Receive function):

           SenderForm.ResultBox.Text = result.ToString();

    3. Configuring MathReceiver
    Now MathReceiver is ready to use. Next you need to configure things so that the framework
    knows when to call your receiver object; you do this by registering an instance of your class with a
    particular URI. The URI depends on the communications channel you wish to use. WSE 2.0
    supports several channels including in-process, TCP, and HTTP. In this step, you're going to use the
    in-process mechanism (we'll look at TCP and HTTP shortly). An in-process URI looks like this:


5
Hands-On Lab Manual: WSE 2.0 Messaging

           soap.inproc://localhost/some/unique/path

        Note: soap.inproc:// schemes must use either localhost or the machine's hostname.

    •   Within Form1's constructor, create an instance of MathReceiver.
    •   Register the instance by calling SoapReceivers static Add method as illustrated here:

           ...
                 public Form1()
                 {
                       InitializeComponent();
                     // construct URI
                     Uri receiverUri = new Uri
           (String.Format("soap.inproc://{0}/{1}",
                        System.Net.Dns.GetHostName(), "receiver"));

                      // initialize and register SOAP receiver object
                      MathReceiver math = new MathReceiver();
                      math.SenderForm = this;
                      SoapReceivers.Add(receiverUri, math);
                 }
           ...

    •   The registered MathReceiver object will now be called any time a message is sent within this
        process to soap.inproc://localhost/receiver,

    4. Sending Messages to the SoapReceiver
    Now you need to send a message to your MathReceiver object.

    •   Write a method called CreateMessage (place this within the Form1 code file) that constructs a
        SoapEnvelope object to model the SOAP envelope shown above:

           ...
           private SoapEnvelope CreateMessage()
           {
               // create SOAP envelope
               SoapEnvelope env = new SoapEnvelope();
                 // set the message's action (the intent)
                 env.Context.Action = String.Format("urn:math:add");
                 // must create body before setting it
                 env.CreateBody();
                 env.Body.InnerXml = String.Format(
                    "<x:add xmlns:x='urn:math'><x>{0}</x><y>{1}</y></x:add>",
                    textBox1.Text, textBox2.Text);
                 return env;
           }

•   Then, double click the form's Add button and write the code to actually send the message. You'll
    do this using SoapSender as illustrated here:

           ...
           private void button1_Click(object sender, System.EventArgs e)
           {
               // construct the same URI receiver listens to
               Uri receiverUri = new Uri(String.Format("soap.inproc://{0}/{1}",
                  System.Net.Dns.GetHostName(), "receiver"));


6
Hands-On Lab Manual: WSE 2.0 Messaging

               // create & send message
               SoapEnvelope env = CreateMessage();
               SoapSender ssender = new SoapSender(receiverUri);
               ssender.Send(env);
           }

    •   Build the project and run the application. Verify that the Add operation works.

    5. Supporting Multiple Operations
    •   Note: At this point you may move onto Lab B in order to save time. These steps repeat
        previous lessons. Lab B does not depend on completion of these steps.

    •   Once you have it working, go back and finish implementing the other operations (Sub, Mul,
        and Div). You'll need to send a distinct SOAP envelope and action value for each one. First,
        generalize your CreateMessage method to accept the operation name:

           ...
           private SoapEnvelope CreateMessage(string op)
           {
               SoapEnvelope env = new SoapEnvelope();
               env.Context.Action = String.Format("urn:math:{0}", op);
               env.CreateBody();
               env.Body.InnerXml = String.Format(
                 "<x:{0} xmlns:x='urn:math'><x>{1}</x><y>{2}</y></x:{0}>",
                 op, textBox1.Text, textBox2.Text);
               return env;
           }

    •   Then, for each button, write the click handler as shown here:

           ...
           private void button1_Click(object sender, System.EventArgs e)
           {
               // create & send message
               SoapEnvelope env = CreateMessage("add");
               SoapSender ssender = new SoapSender(receiverUri);
               ssender.Send(env);
           }
           private void button2_Click(object sender, System.EventArgs e)
           {
               // create & send message
               SoapEnvelope env = CreateMessage("sub");
               SoapSender ssender = new SoapSender(receiverUri);
               ssender.Send(env);
           }
           ...

    •   The last thing you need to do is update MathReceiver to deal with multiple operations. The
        Receive method simply receives a SOAP envelope so it needs to key off of either the request
        element's name, or the message's action to determine which operation to perform. The
        following code fragment illustrates one way to do this:

           public class MathReceiver : SoapReceiver
           {
               ...
               protected override void Receive(SoapEnvelope e)
               {
                  // extract x and y values from incoming SOAP message
                  double x = XmlConvert.ToDouble(
                      e.SelectSingleNode("//x").InnerText);

7
Hands-On Lab Manual: WSE 2.0 Messaging

                   double y = XmlConvert.ToDouble(
                       e.SelectSingleNode("//y").InnerText);
                   double result;

                   // determine which operation to perform from 'action'
                   switch (e.Context.Action)
                   {
                      case "urn:math:add":
                            result = x + y;
                            break;
                      case "urn:math:sub":
                            result = x - y;
                            break;
                      case "urn:math:mul":
                            result = x * y;
                            break;
                      case "urn:math:div":
                            result = x / y;
                            break;
                      default:
                            throw new Exception("unsupported operation");
                   }
                   // write result to sender's form
                   SenderForm.ResultBox.Text = result.ToString();
               }
           }

    •   Build the project and run the application. Verify that all the operations work. It looks like this
        when working properly:




    B. Request/Response Messaging
    In the last example, we used one-way SOAP messages to communicate with the service providing
    the math functionality. We were able to write the result of each operation directly to the Windows
    form because MathReceiver was running in the same process as the form. This would not have
    been possible had the receiver code been running in a separate process (a more typical scenario).

    In cases like this, you need the receiver to send a response message back to the original sender.
    This message exchange pattern is called request/response and is quite common in Web services.
    Implementing request/response is similar to what you just did only now you're going in the
    reverse direction – sending a SOAP message from the receiver back to the original sender.

    1. Getting Started
    •   Open the MessagingReqResp project found in Exercises\Before.
    •   Familiarize yourself with the code (it's the solution to the previous exercise).
    •   Verify that the project contains a reference to the Microsoft.Web.Services assembly and the
        necessary Microsoft.Web.Services namespaces included in Form1.cs. You'll be working in
        Form1.cs for the remainder of the exercise.

    2. Implementing a Response Receiver
    The first step is to create another SoapReceiver object capable of receiving response messages.
    Do the following in Form1.cs:

8
Hands-On Lab Manual: WSE 2.0 Messaging


    •   Define a new class called MathResponseReceiver that derives from SoapReceiver.
    •   Give the class a public field called SenderForm of type Form1 (like before).
    •   Override the Receive method. You class should look something like this:

          public class MathResponseReceiver : SoapReceiver
          {
              // handle to sender's form, must be set before sending message
              public Form1 SenderForm;
               protected override void Receive(SoapEnvelope e)
               {
                  ... // process SOAP message here
               }
          }

    •   Implement the receive method and process the incoming SOAP message. Assume that in this
        case the incoming SOAP envelope looks like this:

          <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
             <s:Body>
                <x:addResponse xmlns:x='urn:math'>
                   <result>99</result>
                </x:addResponse>
             </s:Body>
          </s:Envelope>

    •   Extract the result value using XPath (SelectSingleNode) and write it to the form:

          public class MathResponseReceiver : SoapReceiver
          {
              // handle to sender's form, must be set before sending message
              public Form1 SenderForm;
               protected override void Receive(SoapEnvelope e)
               {
                  // write result to sender's form
                  SenderForm.ResultBox.Text =
                    e.SelectSingleNode("//result").InnerText;
               }
          }

    3. Configuring MathResponseReceiver
    Now MathResponseReceiver is ready to use. Next you need to configure things so the
    framework knows when to call your receiver object; you do this by registering an instance of your
    class with a particular URI. This is exactly like what you did when configuring MathReceiver.

    •   Define a new in-process URI to use for the response messages. It should be different from the
        URI used for the request messages (e.g., soap.inproc://localhost/response).
    •   Within Form1's constructor, create an instance of MathResponseReceiver.
    •   Register the instance by calling SoapReceiver's static Add method specifying the URI. The
        code should look something like this:

          ...
          // target URIs
          /* NOTE: THERE IS ALREADY A DECLARATION FOR receiveUri IN THE
          TEMPLATE */
          private Uri receiverUri = new Uri("soap.inproc://" +
              System.Net.Dns.GetHostName() + "/receiver");
          private Uri responseUri = new Uri("soap.inproc://" +

9
Hands-On Lab Manual: WSE 2.0 Messaging

               System.Net.Dns.GetHostName() + "/response");

           public Form1()
           {
               InitializeComponent();

               // initialize and register SOAP receiver objects
               MathReceiver math = new MathReceiver();
               SoapReceivers.Add(receiverUri, math);
               // response receiver
               MathResponseReceiver mathResponse = new MathResponseReceiver();
               mathResponse.SenderForm = this;
               SoapReceivers.Add(responseUri, mathResponse);
           }

     4. Specifying a Reply Address
     Now you have one receiver object listening for request messages (MathReceiver) and another
     receiver object listening for response messages (MathResponseReceiver). Now we need to
     correlate the two. In other words, MathReceiver should be able to determine where to send
     response messages by simply looking at the incoming request message.

     •   Add a using statement to the Microsoft.Web.Services.Addressing namespace:

           ...
           using Microsoft.Web.Services.Addressing;

     •   Specify the return address using the SoapEnvelope.Context.ReplyTo property when
         creating the SOAP request messages within the CreateMessage method:

           private SoapEnvelope CreateMessage(string op)
           {
               // create SOAP message
               SoapEnvelope env = new SoapEnvelope();
               env.Context.Action = String.Format("urn:math:{0}", op);
               env.Context.ReplyTo = new ReplyTo(responseUri);

               ... // continue creating envelope like before
           }

     5. Sending a Response Message
     Now that the SOAP envelope contains the ReplyTo address, MathReceiver can use that
     information to figure out where to send the response.

     •   Update MathReceiver's Receive method to send a response back to the original sender,
         using the address specified in SoapEnvelope.Context.ReplyTo. You'll need to use another
         SoapSender object to do this as illustrated here (Edit the MathReceiver.Receive function):

           public class MathReceiver : SoapReceiver
           {
               protected override void Receive(SoapEnvelope e)
               {
                     ... // process incoming envelope (like before)

                      // send response message to original sender
                      SoapEnvelope env = new SoapEnvelope();
                      env.Context.Action = e.Context.Action;
                      env.CreateBody();


10
Hands-On Lab Manual: WSE 2.0 Messaging

                     env.Body.InnerXml = String.Format("<x:{0}Response
           xmlns:x='urn:math'><result>{1}</result></x:{0}Response>",
           e.Body.SelectSingleNode("*").LocalName, result);

                       // create SoapSender for the reply address
                       // and send message
                       SoapSender responseSender = new SoapSender(
                            e.Context.ReplyTo);
                       responseSender.Send(env);
           }

     •   Build the project and run the application. Verify that all the operations work.

     C. Higher-Level Messaging
     In the preceding exercises you manually performed two common but tedious tasks. The first task
     was to determine which operation to process based on the incoming SOAP message. You did this
     within the Receive method by inspecting the message's action value. The second task was that of
     correlating response messages with request messages. You accomplished this by inspecting the
     ReplyTo value in the incoming message and sending another message back to the original sender.
     When using SoapSender and SoapReceiver, you're always required to manually handle:

            •   Multiple operations within a given SoapReceiver object
            •   Correlating response messages with request messages

     Since both tasks are quite common in messaging scenarios, WSE 2.0 offers a higher-level
     messaging API that builds on SoapSender and SoapReceiver. The higher-level API is designed
     in terms of two classes called SoapClient and SoapService. These classes automatically handle
     the tasks outlined above for you and make it easier to get things up and running.

     Now you're going to port the previous solution to use SoapClient and SoapService.

     1. Getting Started
     •   Open the MessagingHigherLevel project found in Exercises\Before.
     •   Familiarize yourself with the code.
     •   Verify that the project contains a reference to the Microsoft.Web.Services assembly and the
         necessary Microsoft.Web.Services namespaces included in Form1.cs. You'll be working in
         Form1.cs for the remainder of the exercise.

     2. Implementing a SoapService
     SoapService derives from SoapReceiver and provides the basic functionality that most receivers
     need. Hence, you no longer need to implement a SoapReceiver class in your project. Now you're
     going to implement a SoapService class to serve as your SOAP endpoint.

     •   At the bottom of Form1.cs, define a new class called MathService that derives from
         SoapService as illustrated here:

           public class MathService : SoapService
           {
               ... // define operations here
           }

     •   Implement your SOAP operations as methods within MathService (e.g., Add, Sub, Mul, and
         Div). Each method should take a SoapEnvelope as input and return a SoapEnvelope as
         output. Here's how the Add and Sub methods should look (Note: this code only implements
         Add and Sub):

11
Hands-On Lab Manual: WSE 2.0 Messaging

           public class MathService : SoapService
           {
               public SoapEnvelope Add(SoapEnvelope e)
               {
                     double x = XmlConvert.ToDouble(
                       e.SelectSingleNode("//x").InnerText);
                     double y = XmlConvert.ToDouble(
                       e.SelectSingleNode("//y").InnerText);
                     return CreateResponseMessage(e, x+y);
               }
               public SoapEnvelope Sub(SoapEnvelope e)
               {
                     double x = XmlConvert.ToDouble(
                       e.SelectSingleNode("//x").InnerText);
                     double y = XmlConvert.ToDouble(
                       e.SelectSingleNode("//y").InnerText);
                     return CreateResponseMessage(e, x-y);
               }
               ...
           }

     •   Write the CreateResponseMessage method to create another SoapEnvelope containing the
         supplied response and the same action as the request message. Add this code to the
         MathService class.
           private SoapEnvelope CreateResponseMessage(SoapEnvelope e, double
           result)
           {
                // send response SOAP message
                SoapEnvelope env = new SoapEnvelope();
                env.Context.Action = e.Context.Action;
                env.CreateBody(); // must create body before setting it
                env.Body.InnerXml = String.Format("<x:{0}Response
           xmlns:x='urn:math'><result>{1}</result></x:{0}Response>",
           e.Body.SelectSingleNode("*").LocalName, result);
                return env;
           }


     •   Next, you must annotate each method with the SoapMethod attribute indicating the SOAP
         action value associated with the particular method. This allows the WSE 2.0 infrastructure to
         figure out which method to call when it receives the SOAP message.

           public class MathService : SoapService
           {
               [SoapMethod("urn:math:add")]
               public SoapEnvelope Add(SoapEnvelope e)
               {
                     double x = XmlConvert.ToDouble(
                       e.SelectSingleNode("//x").InnerText);
                     double y = XmlConvert.ToDouble(
                       e.SelectSingleNode("//y").InnerText);
                     return CreateResponseMessage(e, x+y);
               }
               [SoapMethod("urn:math:sub")]
               public SoapEnvelope Sub(SoapEnvelope e)
               {
                     double x = XmlConvert.ToDouble(
                       e.SelectSingleNode("//x").InnerText);
                     double y = XmlConvert.ToDouble(
                       e.SelectSingleNode("//y").InnerText);
                     return CreateResponseMessage(e, x-y);
               }
               ...
12
Hands-On Lab Manual: WSE 2.0 Messaging

           }

     3. Configuring MathService
     •   You configure the MathService object just like you did before with the MathReceiver object.
         You need to register it with SoapReceivers and bind it to a URI as shown here:

           ...
           // target URIs
           private Uri receiverUri = new Uri("soap.inproc://" +
               System.Net.Dns.GetHostName() + "/receiver");
           public Form1()
           {
               InitializeComponent();
                // initialize and register SOAP service object
                MathService mathService = new MathService();
                SoapReceivers.Add(receiverUri, mathService);
           }

     4. Implementing a SoapClient
     As with SoapService, you need to implement another class that derives from SoapClient. It will
     encapsulate the process of using SoapSender to send messages to a particular endpoint. Hence,
     using SoapClient, you no longer need to implement a SoapSender object. Now you're going to
     implement a SoapClient class to serve as your sending mechanism.

     •   Define a new class named MathClient that derives from SoapClient as illustrated here:

           public class MathClient : SoapClient
           {
               public MathClient() {}
               public MathClient(Uri uri) : base(uri) {}

                // operations go here
                ...
           }

     •   As with MathService, implement your SOAP operations as methods within MathClient (e.g.,
         Add, Sub, Mul, and Div). Each method should take a SoapEnvelope as input and return a
         SoapEnvelope as output.
     •   Annotate each method with the SoapMethod attribute using the same SOAP action value that
         you used in the corresponding method in SoapService.
     •   Then, within each method, call SendRequestResponse (base class) and return the response
         SoapEnvelope object as illustrated below. SendRequestResponse takes care of invoking
         the operation and correlating the request/response messages. This code acts like a traditional
         ASP.NET Web Service Proxy.

           public class MathClient : SoapClient
           {
               public MathClient() {}
               public MathClient(Uri uri) : base(uri) {}
                [SoapMethod("urn:math:add")]
                public SoapEnvelope Add(SoapEnvelope e)
                {
                      return base.SendRequestResponse("Add", e);
                }
                [SoapMethod("urn:math:sub")]
                public SoapEnvelope Sub(SoapEnvelope e)
                {
13
Hands-On Lab Manual: WSE 2.0 Messaging

                      return base.SendRequestResponse("Sub", e);
               }
               ...
           }

     5. Using a SoapClient
     You can now use an instance of MathClient to send SOAP messages to a particular endpoint. An
     instance of MathService serves as that endpoint in this case.

     •   Locate the supplied method called CreateMessageAndSend.
     •   After the line that creates the SoapEnvelope object, create an instance of MathClient
         supplying the URI bound to MathService to the constructor (in this case receiverUri).
     •   Then, for each operation, call the appropriate MathClient method as illustrated here:

           private void CreateMessageAndSend(string op)
           {
               // create & send message
               SoapEnvelope reqEnv = CreateMessage(op);
               MathClient mathClient = new MathClient(receiverUri);
               SoapEnvelope respEnv = null;
               switch(op)
               {
                     case "add":
                           respEnv = mathClient.Add(reqEnv);
                           break;
                     case "sub":
                           respEnv = mathClient.Sub(reqEnv);
                           break;
                     case "mul":
                           respEnv = mathClient.Mul(reqEnv);
                           break;
                     case "div":
                           respEnv = mathClient.Div(reqEnv);
                           break;
                     default:
                           throw new Exception("unsupported operation");
               }
               this.textBox3.Text =
                  respEnv.SelectSingleNode("//result").InnerText;
           }

     •   Extract the result value from the response SoapEnvelope and display it in the form.
     •   Build the project and run the application. Verify that all the operations work.
     •   Note: If you do not implement Mul and Div you will get a compile error.

     D. Using TCP
     Up to this point in the lab, the client code and the Web service code have been running in the
     same process. The WSE 2.0 messaging API is flexible enough to allow for this along with other
     more advanced communications mechanisms like TCP and HTTP.

     In this exercise, we've separated the client code from the Web service code and put them in
     separate projects (meaning they'll run in separate processes). You're going to use TCP as the
     communications mechanism between the two applications.

     1. Getting Started
     •   Open the MessagingTcpService project found in Exercises\Before and familiarize yourself
         with the code. This project contains the MathService class (already implemented, like the one
         in the last exercise) and an empty form that simply displays the URI that MathService is
         bound to. The form looks like this when running:
14
Hands-On Lab Manual: WSE 2.0 Messaging




     •   The only thing you have to change in this project is the URI used by the receiver object.
     •   Open the MessagingTcpClient project found in Exercises\Before and familiarize yourself
         with the code. This project contains the MathClient class (already implemented, like the one
         in the last exercise) and the math form you've been using so far. The only thing you have to
         change in this project is the URI being used.

     2. Using TCP to Send/Receive Messages
     •   Open Form1.cs in the MessagingTcpService project and find the Form1 constructor. In the
         constructor, initialize the receiverUri field with a new URI. In this case, you're going to use
         TCP as the communications mechanism so the URI needs to take the following form:

           soap.tcp://hostname:port/some/unique/path

     •   The constructor then instantiates a MathService object and registers it with the new URI.
     •   The following shows how to construct the URI based on the lab machine's name:

           public Form1()
           {
               InitializeComponent();
                // set MathService URI, use TCP
                receiverUri = new Uri(String.Format(
                      "soap.tcp://{0}/receiver",
                      System.Net.Dns.GetHostName()));

                // initialize and register SOAP receiver objects
                MathService mathService = new MathService();
                SoapReceivers.Add(receiverUri, mathService);
           }

     •   Build the project and verify that it runs. The form should display the URI it's receiving on.
     •   Next, open Form1.cs in MessagingTcpClient and do the same thing. Locate the constructor
         and initialize the receiverUri member to the same TCP URI that you used in the server.
     •   Build the project and verify that it runs.
     •   Now try invoking one of the math operations and verify that it works.

     3. Tracing TCP Messages
     Now you're going to trace the TCP messages to see what they look like.

     •   Open the Microsoft SOAP Toolkit Version 3 Trace Utility by selecting Start | All
         Programs | Microsoft SOAP Toolkit Version 3 | Trace Utility.
     •   Start a new trace by selecting File | New | Unformatted Trace. Make sure you select
         Unformatted Trace.
     •   Specify the TCP port that you want the trace utility to listen on (use 123) and the TCP port
         that you want the trace utility to forward to (use 456). The dialog should look like this:




15
Hands-On Lab Manual: WSE 2.0 Messaging




     •   Go back to Form1.cs in the client project and update the URI to include the port number as
         illustrated here:

           public Form1()
           {
               InitializeComponent();
                // set MathService URI, use TCP
                receiverUri = new Uri(String.Format(
                      "soap.tcp://{0}:123/receiver",
                      System.Net.Dns.GetHostName()));
           }

     •   Go back to Form1.cs in the service project and update the URI to include the port number as
         illustrated here:

           public Form1()
           {
               InitializeComponent();
                // set MathService URI, use TCP
                receiverUri = new Uri(String.Format(
                      "soap.tcp://{0}:456/receiver",
                      System.Net.Dns.GetHostName()));

                // initialize and register SOAP receiver objects
                MathService mathService = new MathService();
                SoapReceivers.Add(receiverUri, mathService);
           }

     •   Rebuild both projects and verify that they run.
     •   When you invoke an operation, the SOAP trace utility will capture the messages and allow you
         to inspect them. Take a few minutes and inspect the messages used in the operations. The
         following image illustrates what the trace will look like – I've highlighted the soap:Envelope.




16
Hands-On Lab Manual: WSE 2.0 Messaging




     E. Using HTTP
     In addition to the in-process and TCP communications mechanisms, the WSE 2.0 messaging API
     also integrates with ASP.NET's HTTP pipeline. This exercise is a lot like the last in that the client
     code has been separated from the service code. Now you're going to configure things in ASP.NET
     so that it knows to call your MathService endpoint.

     1. Getting Started
     •   Open the MessagingHttpService project found in Exercises\Before and familiarize yourself
         with the code. This project contains the MathService class (already implemented). Your task
         in is to write a web.config file that configures MathService (located in form1.cs file) as an
         HTTP handler.
     •   Open the MessagingHttpClient project found in Exercises\Before and familiarize yourself
         with the code. This project contains the MathClient class (already implemented, like the one
         in the previous exercises) and the form you've been using. The only thing you have to change
         in this project is the URI being used. You will perform this operation later in this lab.

     2. Configuring SoapReceivers in ASP.NET
     •   SoapReceiver implements the IHttpHandler interface (see below), which makes it possible
         for any derived class to be configured in the ASP.NET pipeline as a handler. (Note: You do not
         have to implement a SoapReceiver – this is for education purposes only).

           public abstract class SoapReceiver : SoapPort, IHttpHandler
           {
              ...
           }

     •   You configure a class to serve as an HTTP handler in the virtual directory's web.config file.
         Open web.config found in the MessagingHttpService project and add a new handler
         mapping. You do this by specifying what class to call for a given verb/path combination.
     •   Your complete web.config should look like this:

           <configuration>
               <system.web>
17
Hands-On Lab Manual: WSE 2.0 Messaging

                     <httpHandlers>
                           <add verb="*" path="receiver.ashx"
                             type="MessagingSample.MathService, Messaging"/>
                     </httpHandlers>
               </system.web>
           </configuration>

     •   Now ASP.NET will create an instance of MathService for each message that arrives at this
         HTTP endpoint targeted at receiver.ashx. The .ASHX extension implements a generic
         SoapReceiver. Since ASP.NET takes care of instantiating the MathService object, you don't
         have to setup a listener object ahead of time (like you did in previous examples through
         SoapReceivers.Add).
     •   When you are finished editing the web.config compile the project.

     3. Creating a Virtual Directory
     Before you can start sending messages to this endpoint, you need to configure the physical
     directory as a virtual directory in IIS.

     •   Right click on the service project directory (Exercises\Before\MessagingHttpService) in
         Windows Explorer and select Sharing and Security.
     •   Select the Web Sharing tab and press Share this folder. Leave the virtual alias the same as
         the directory name, leave the default permissions. The dialog should look like this:




     •   Press OK.
     •   The Web Share dialog should now look like this:




18
Hands-On Lab Manual: WSE 2.0 Messaging




     •   Now you have a virtual directory (accessible via http://localhost/messaginghttpservice)
         that maps to the physical directory the project is in.
     •   Open the Control Panel and select Administrative Tools | Internet Information Services.
     •   Locate the virtual directory you just created within the default Web site.
     •   Right click on the virtual directory and select Properties | Directory Security | Edit.
     •   Enable Anonymous Access. The dialog should look like this:




19
Hands-On Lab Manual: WSE 2.0 Messaging




     •   Press OK.

     4. Running the Client
     •   Open Form1.cs in MessagingHttpClient and specify the URL to your new HTTP endpoint.
         Locate the Form1 constructor and initialize the receiverUri member to
         http://localhost/messaginghttpservice/receiver.ashx.
     •   Build the project and verify that it runs.
     •   Now try invoking one of the math operations and verify that it works.

     5. Tracing HTTP Messages
     •   Open the Microsoft SOAP Toolkit Version 3 Trace Utility by selecting Start | All
         Programs | Microsoft SOAP Toolkit Version 3 | Trace Utility.
     •   Start a new trace by selecting File | New | Formatted Trace.
     •   Specify the TCP port that you want the trace utility to listen on (use 8080)
     •   Specify the TCP port that you want the trace utility to forward to (use 80 to route to IIS).
     •   Go back to Form1.cs in the client project and update the URI to include the port number as
         illustrated here: http://localhost:8080/messaginghttpservice/receiver.ashx.
     •   Rebuild the client project and run it again.
     •   When you invoke an operation, the SOAP trace utility will capture the messages and allow you
         to inspect them. Take a few minutes and inspect the messages sent over HTTP.

     F. WSE2 Chat Program (Time Permitting)
     In this final exercise, you're going to build a chat program with the WSE 2.0 messaging APIs
     you've been using so far. The chat program should allow the user to specify a username and port
     number. Then, when the user clicks Listen, it constructs a URI based on those values and the
     program begins listening over TCP.


20
Hands-On Lab Manual: WSE 2.0 Messaging

     The user can type in a target URI indicating where to send the chat messages. Then, the user
     types a message and presses Send (at the bottom of the form) and the application should send
     the message over TCP to the target URI. These images illustrate how everything works:




     1. Getting Started
     •   Open the WseChat project found in Exercises\After and try running the application. Run two
         instances of the application and have them listen on different ports (see above). Then verify
         that you can send messages between them as illustrate in the images.

     2. Implementing WseChat
     •   Now open the WseChat project found in Exercises\Before and familiarize yourself with the
         skeleton code. Your job is to finish implementing the application on your own! If you get stuck,
         take a peak at the solution in the After directory. You can implement this project using any of
         the techniques you've used throughout the previous exercises. Good luck!


Summary
WSE 2.0 provides a flexible API for sending and receiving SOAP messages in-process, via TCP, or via
HTTP. SoapSender and SoapReceiver provide the basic functionality for "sending" and "receiving"
SOAP messages. WSE 2.0 also provides a higher-level API through the SoapClient and SoapService
classes. These classes facilitate dealing with multiple operations at a given endpoint and correlating
the request and response messages, simplifying the overall process of building message-oriented Web
services. WSE 2.0 takes a large step towards realizing the full potential of XML Web services.




21

				
DOCUMENT INFO
Shared By:
Categories:
Tags:
Stats:
views:4
posted:11/14/2012
language:Unknown
pages:21