ConversationClient.asmx.cs Sample

This topic inludes the source code for the ConversationClient.asmx.cs Sample.

Sample Location

This sample is located in the following directory in your WebLogic Workshop installation:

BEA_HOME/weblogic81/samples/workshop/SamplesApp/WebServices/interop/dotNET/

Sample Source Code


001 using System;
002 using System.ComponentModel;
003 using System.Diagnostics;
004 using System.Web.Services;
005 using System.IO;
006 
007 namespace test
008 {
009   /// <summary>
010   /// This is an example of a .NET web service that is a client of
011   /// a WebLogic Workshop web service.  The target web service,
012   /// samples/async/Conversation.jws, is conversational and optionally
013   /// uses callbacks.  This client is fully capable of paticipating in
014   /// conversations with Conversation.jws and can also receive callbacks.
015   /// </summary>
016   
017   /*
018    * This Namespace declaration is required to cause the callback
019    * handler (onResultReady) to be in the proper namespace.  Ideally,
020    * we could set the namespace on a per-method basis, but .NET doesn't
021    * appear to allow that.
022    */
023   [WebService(Namespace="http://www.openuri.org/")]
024   public class ConversationClient : System.Web.Services.WebService
025   {
026 
027     public ConversationClient()
028     {
029       //CODEGEN: This call is required by the ASP.NET Web Services Designer
030       InitializeComponent();
031     }
032 
033     #region Component Designer generated code
034     
035     //Required by the Web Services Designer 
036     private IContainer components = null;
037         
038     /// <summary>
039     /// Required method for Designer support - do not modify
040     /// the contents of this method with the code editor.
041     /// </summary>
042     private void InitializeComponent()
043     {
044     }
045 
046     /// <summary>
047     /// Clean up any resources being used.
048     /// </summary>
049     protected override void Disposebool disposing )
050     {
051       if(disposing && components != null)
052       {
053         components.Dispose();
054       }
055       base.Dispose(disposing);    
056     }
057     
058     #endregion
059 
060     /*
061      * start invokes the Conversation web service's startRequest
062      * operation.
063      
064      * Since the Conversation web service is conversational,
065      * we must also prepare a SOAP header containing a conversation ID.
066      
067      * Since the Conversation web service can optionally communicate
068      * the result of it's work via a callback, we must prepare a
069      * second SOAP header containing the "callbackLocation", which is
070      * the URL of the recipient to which callbacks should be sent.
071      */
072     [WebMethod(EnableSession=true)]
073     public void start(Boolean useCallbacks, Boolean useIPAddress)
074     {
075       /*
076        * The Conversation proxy was created using .NET's wsdl.exe
077        * application and the Conversation.jws's WSDL file.  The WSDL
078        * file for any WebLogic Workshop web service may be obtained
079        * by hitting the web service's URL with "?WSDL" appended to
080        * the end.  For example:
081        
082        * http://somehost:7001/samples/async/Conversation.jws?WSDL
083        
084        * wsdl.exe produces a C# proxy class.  Place the resulting
085        * Conversation.cs file in your .NET project, then use Visual
086        * Studio's Project->Add Existing Item menu action to "import"
087        * the class into the project.
088        */
089       Conversation conv;
090       String conversationID;
091       String callbackLocation;
092       int asmxIndex;
093 
094       /*
095        * Construct the callback location from various pieces of
096        * server and HttpRequest info.
097        */
098       Uri requestUrl = Context.Request.Url;
099 
100       ifuseIPAddress )
101       {
102         /*
103          * if useIPAddress is true, construct the callbackLocation
104          * with the IP address of this host.
105          */
106         callbackLocation = requestUrl.Scheme + "://" +
107           System.Net.Dns.GetHostByName(Context.Server.MachineName).AddressList[0+
108           ":" + requestUrl.Port + requestUrl.AbsolutePath;
109       }
110       else 
111       {
112         /*
113          * if useIPAddress is false, construct the callbackLocation
114          * with the hostname of this host.
115          */
116         callbackLocation = requestUrl.Scheme + "://" +
117           Context.Server.MachineName +
118           ":" + requestUrl.Port + requestUrl.AbsolutePath;
119       }
120 
121       // Remove everything after ".asmx"
122       asmxIndex = callbackLocation.IndexOf(".asmx"5;
123       callbackLocation = callbackLocation.Remove(asmxIndex,
124                              callbackLocation.Length - asmxIndex);
125 
126       /*
127        * Make up a conversation ID for this conversation.  It must
128        * be guaranteed unique across all converations on the target
129        * web service's server.
130        
131        * Here we use a string composed of the current process ID
132        * and the current date and time.  That's not completely
133        * reliable since this client could possibly start two
134        * conversations within the space of a second (the resolution
135        * of DateTime.ToString()).
136        */
137       conversationID = Process.GetCurrentProcess().Id + " - " +
138                       DateTime.Now.ToString();
139 
140       /*
141        * Create an instance of the proxy for the Conversation
142        * web service.
143        */
144       conv = new Conversation();
145 
146       /*
147        * Construct a conversation start header and set conversation ID
148        * and callback location.
149        */
150       conv.StartHeaderValue = new StartHeader();
151       conv.StartHeaderValue.conversationID = conversationID;
152       conv.StartHeaderValue.callbackLocation = callbackLocation;
153 
154       /*
155        * Persist the conversationID in session state so that it can
156        * be used in other methods that take part in the conversation.
157        
158        * This is not safe since one session could start multiple
159        * conversations, but there is no other apparent way to persist
160        * this information.  Member variables of WebService classes
161        * are not persisted across method invocations.
162        */
163       Session["ConversationID"= conversationID;
164 
165       /*
166        * Invoke the startRequest method of the web service. The
167        * single boolean parameter determines whether the Conversation
168        * web service will use callbacks to communicate the result
169        * back to this client.
170        
171        * If the argument is true, an onResultReady callback will
172        * be sent when the result is ready.  This client must implement
173        * a method with that name that expects the message shape defined
174        * by the target web service (returns void and accepts a single
175        * string argument).  See the onResultReady method below.
176        
177        * If the argument to startRequest is false, callbacks will not
178        * be used and this client must use the getRequestStatus method
179        * to poll the Conversation web service for the result.
180        */
181       conv.startRequest(useCallbacks);
182     }
183 
184     /*
185      * getStatus invokes Conversation's getRequestStatus method.
186      * getRequestStatus is a polling method that is an alternative
187      * for web services that cannot recieve callbacks.
188      
189      * Note that a conversation must be started with startRequest before
190      * this method may be invoked.  If not, or if this method is invoked
191      * outside of a conversation for any reason, it will get back a SOAP
192      * fault indicating that the conversation does not exist.
193      */
194     [WebMethod(EnableSession=true)]
195     public String getStatus()
196     {
197       String result;
198 
199       /*
200        * Create an instance of the proxy for the Conversation
201        * web service.  We could probably persist the proxy instance
202        * in session state, but chose not to.
203        */
204       Conversation conv = new Conversation();
205 
206       /*
207        * Construct a conversation continue header and set the
208        * conversation ID to the one we cached on session state in
209        * the start method.
210        */
211       conv.ContinueHeaderValue = new ContinueHeader();
212       conv.ContinueHeaderValue.conversationID = (String)Session["ConversationID"];
213 
214         /* 
215        * Invoke the getRequestStatus method of the web service.
216        */
217       result = conv.getRequestStatus();
218       return result;
219     }
220 
221     /*
222      * finish invokes Conversation's terminateRequest method, which
223      * terminates the current conversation.
224      
225      * Note that a conversation must be started with startRequest before
226      * this method may be invoked.  If not, or if this method is invoked
227      * outside of a conversation for any reason, it will get back a SOAP
228      * fault indicating that the conversation does not exist.
229      */
230     [WebMethod(EnableSession=true)]
231     public void finish()
232     {
233       /*
234        * Create an instance of the proxy for the Conversation
235        * web service.  We could probably persist the proxy instance
236        * in session state, but chose not to.
237        */
238       Conversation conv = new Conversation();
239 
240       /*
241        * Construct a conversation continue header and set the
242        * conversation ID to the one we cached on session state in
243        * the start method.  Both "continue" and "finish" methods
244        * use the same SOAP header format.
245        */
246       conv.ContinueHeaderValue = new ContinueHeader();
247       conv.ContinueHeaderValue.conversationID =  (String)Session["ConversationID"];
248 
249       /* 
250        * Invoke the terminateRequest method of the web service.
251        */
252       conv.terminateRequest();
253     }
254 
255     /*
256      * onResultReady is a callback handler for the onResultReady
257      * callback that Conversation.jws can optionally use to return
258      * its results.
259      
260      * .NET does not support callbacks directly, but a callback is just
261      * a method invocation message.  So if you construct a WebMethod with
262      * the same signature as the callback and set the XML namespace
263      * properly, it serves as a callback handler.
264      
265      * The namespace of this entire WebService is set to match that
266      * required by the callback ("http://www.openuri.org/") using the
267      * [WebService(Namespace=...)] attribute at the top of this file.
268      * Ideally we could set the namespace on a per-method basis, but
269      * .NET doesn't appear to allow that.
270      */
271     [WebMethod]
272     public void onResultReady(String result)
273     {
274       /*
275        * When the callback is invoked, log a message to the
276        * hardcoded file c:\temp\ConversationClient.log.
277        
278        * Note: if c:\temp does not exist on this server, an
279        * Exception will be raised.  Since it is not handled here,
280        * it will be returned as a SOAP fault to the Conversation
281        * web service.
282        */
283       TextWriter output;
284       output = File.AppendText("c:\\temp\\ConversationClient.log");
285       String msg = "[" + DateTime.Now.ToString() "] callback received";
286       output.WriteLine(msg);
287       output.Flush();
288       output.Close();
289     }
290   }
291 }