Thanks to Lluis' work on the XmlSerializer it is now possible to perform
authorMiguel de Icaza <miguel@gnome.org>
Fri, 30 May 2003 04:32:14 +0000 (04:32 -0000)
committerMiguel de Icaza <miguel@gnome.org>
Fri, 30 May 2003 04:32:14 +0000 (04:32 -0000)
a Soap invocation.

The result is still not handled though.

2003-05-29  Miguel de Icaza  <miguel@ximian.com>

* SoapHttpClientProtocol.cs (CreateMessage): Kill.  Move
functionality to Invoke.

(Invoke): Use new TypeStubInfo/MethodStubInfo instead.

* SoapClientMessage.cs: Drop old mechanism, use MethodStubInfo instead.

* Methods.cs: New file.  Contains the managed for TypeStubs and
MethodInfoStubs.

A MethodInfoStub contains the serializers we use for the SOAP
request.

* SoapClientMessage.cs: Drop parameters from the clientmessage, it
does not belong here.  Drop oneway, we canextract that from the
SoapDocumentMethodAttribute class that we pass.

svn path=/trunk/mcs/; revision=15003

mcs/class/System.Web.Services/System.Web.Services.Protocols/ChangeLog
mcs/class/System.Web.Services/System.Web.Services.Protocols/Methods.cs [new file with mode: 0644]
mcs/class/System.Web.Services/System.Web.Services.Protocols/NOTES
mcs/class/System.Web.Services/System.Web.Services.Protocols/SoapClientMessage.cs
mcs/class/System.Web.Services/System.Web.Services.Protocols/SoapHttpClientProtocol.cs
mcs/class/System.Web.Services/list

index 0604061dd80d533d5b7b7972db7e603f6d376f6e..315fed67be6beb02bd4326d4919dfbba10f45ff7 100644 (file)
@@ -1,3 +1,22 @@
+2003-05-29  Miguel de Icaza  <miguel@ximian.com>
+
+       * SoapHttpClientProtocol.cs (CreateMessage): Kill.  Move
+       functionality to Invoke.
+
+       (Invoke): Use new TypeStubInfo/MethodStubInfo instead.
+
+       * SoapClientMessage.cs: Drop old mechanism, use MethodStubInfo instead.
+
+       * Methods.cs: New file.  Contains the managed for TypeStubs and
+       MethodInfoStubs.   
+
+       A MethodInfoStub contains the serializers we use for the SOAP
+       request. 
+
+       * SoapClientMessage.cs: Drop parameters from the clientmessage, it
+       does not belong here.  Drop oneway, we canextract that from the
+       SoapDocumentMethodAttribute class that we pass.
+
 2003-05-28  Miguel de Icaza  <miguel@ximian.com>
 
        * LogicalMethodInfo.cs (Create): Implement begin/end method
diff --git a/mcs/class/System.Web.Services/System.Web.Services.Protocols/Methods.cs b/mcs/class/System.Web.Services/System.Web.Services.Protocols/Methods.cs
new file mode 100644 (file)
index 0000000..fdcc54d
--- /dev/null
@@ -0,0 +1,295 @@
+//
+// Methods.cs: Information about a method and its mapping to a SOAP web service.
+//
+// Author:
+//   Miguel de Icaza
+//
+// (C) 2003 Ximian, Inc.
+//
+//
+
+using System.Reflection;
+using System.Collections;
+using System.Xml.Serialization;
+using System.Web.Services;
+using System.Web.Services.Description;
+
+namespace System.Web.Services.Protocols {
+
+       //
+       // This class represents all the information we extract from a MethodInfo
+       // in the SoapHttpClientProtocol derivative stub class
+       //
+       internal class MethodStubInfo {
+               internal LogicalMethodInfo MethodInfo;
+
+               // The name used bythe stub class to reference this method.
+               internal string Name;
+               
+               internal string Action;
+               internal string Binding;
+
+               // The name/namespace of the request 
+               internal string RequestName;
+               internal string RequestNamespace;
+
+               // The name/namespace of the response.
+               internal string ResponseName;
+               internal string ResponseNamespace;
+               
+               internal bool   OneWay;
+               internal SoapParameterStyle ParameterStyle;
+               internal SoapBindingUse Use;
+
+               internal XmlSerializer RequestSerializer;
+               internal XmlSerializer ResponseSerializer;
+               
+               //
+               // Constructor
+               //
+               MethodStubInfo (TypeStubInfo parent, LogicalMethodInfo source, SoapDocumentMethodAttribute dma, XmlReflectionImporter importer)
+               {
+                       MethodInfo = source;
+
+                       Use = dma.Use;
+                       if (Use == SoapBindingUse.Default)
+                               Use = parent.Use;
+                       if (Use != SoapBindingUse.Literal)
+                               throw new Exception ("Only SoapBindingUse.Literal supported");
+                       
+                       OneWay = dma.OneWay;
+                       if (OneWay){
+                               if (source.ReturnType != typeof (void))
+                                       throw new Exception ("OneWay methods should not have a return value");
+                               if (source.OutParameters.Length != 0)
+                                       throw new Exception ("OneWay methods should not have out/ref parameters");
+                       }
+                       
+                       Action = dma.Action;
+                       Binding = (dma.Binding == "" ? parent.BindingName : dma.Binding);
+                       RequestName = dma.RequestElementName;
+                       if (RequestName == "")
+                               RequestName = source.Name;
+                       
+                       RequestNamespace = dma.RequestNamespace;
+                       ResponseName = dma.ResponseElementName;
+                       ResponseNamespace = dma.ResponseNamespace;
+                       ParameterStyle = dma.ParameterStyle;
+                       if (ParameterStyle == SoapParameterStyle.Default)
+                               ParameterStyle = parent.ParameterStyle;
+
+                       object [] o = source.GetCustomAttributes (typeof (WebMethodAttribute));
+                       if (o.Length == 1){
+                               WebMethodAttribute wma = (WebMethodAttribute) o [0];
+
+                               Name = wma.MessageName;
+                               if (Name == "")
+                                       Name = source.Name;
+                       } else
+                               Name = source.Name;
+
+                       if (ResponseName == "")
+                               ResponseName = Name + "Response";
+                       
+                       MakeRequestSerializer (importer);
+                       MakeResponseSerializer (importer);
+               }
+
+               static internal MethodStubInfo Create (TypeStubInfo parent, LogicalMethodInfo lmi, XmlReflectionImporter importer)
+               {
+                       object [] o = lmi.GetCustomAttributes (typeof (SoapDocumentMethodAttribute));
+                       if (o.Length == 0){
+                               lmi.GetCustomAttributes (typeof (SoapRpcMethodAttribute));
+                               if (o.Length != 0)
+                                       throw new Exception ("SoapRpcMethod not supported, only SoapDocumentMethod");
+                               return null;
+                       }
+
+                       return new MethodStubInfo (parent, lmi, (SoapDocumentMethodAttribute) o [0], importer);
+               }
+
+               void MakeRequestSerializer (XmlReflectionImporter importer)
+               {
+                       ParameterInfo [] input = MethodInfo.InParameters;
+                       XmlReflectionMember [] in_members = new XmlReflectionMember [input.Length];
+                       
+                       for (int i = 0; i < input.Length; i++){
+                               XmlReflectionMember m = new XmlReflectionMember ();
+                               m.IsReturnValue = false;
+                               m.MemberName = input [i].Name;
+                               m.MemberType = input [i].ParameterType;
+
+                               in_members [i] = m;
+                       }
+
+                       TypeStubInfo.SingleMembersMapping [0] =
+                               importer.ImportMembersMapping (RequestName, RequestNamespace, in_members, true);
+                       XmlSerializer [] s = XmlSerializer.FromMappings (TypeStubInfo.SingleMembersMapping);
+                       RequestSerializer = s [0];
+               }
+
+               void MakeResponseSerializer (XmlReflectionImporter importer)
+               {
+                       ParameterInfo [] output = MethodInfo.OutParameters;
+                       XmlReflectionMember [] out_members = new XmlReflectionMember [(OneWay ? 0 : 1) + output.Length];
+                       XmlReflectionMember m;
+                       int idx = 0;
+
+                       if (!OneWay){
+                               m = new XmlReflectionMember ();
+                               m.IsReturnValue = true;
+                               m.MemberName = RequestName + "Result";
+                               m.MemberType = MethodInfo.ReturnType;
+                               idx++;
+                               out_members [0] = m;
+                       }
+                       
+                       for (int i = 0; i < output.Length; i++){
+                               m = new XmlReflectionMember ();
+                               m.IsReturnValue = false;
+                               m.MemberName = output [i].Name;
+                               m.MemberType = output [i].ParameterType;
+
+                               if (m.MemberType.IsByRef)
+                                       m.MemberType = m.MemberType.GetElementType ();
+                               out_members [i + idx] = m;
+                       }
+
+                       TypeStubInfo.SingleMembersMapping [0] =
+                               importer.ImportMembersMapping (RequestName, RequestNamespace, out_members, true);
+                       XmlSerializer [] s = XmlSerializer.FromMappings (TypeStubInfo.SingleMembersMapping);
+                       ResponseSerializer = s [0];
+               }
+       }
+
+       //
+       // Holds the metadata loaded from the type stub, as well as
+       // the metadata for all the methods in the type
+       //
+       internal class TypeStubInfo {
+               Hashtable name_to_method = new Hashtable ();
+
+               // Precomputed
+               internal SoapParameterStyle      ParameterStyle;
+               internal SoapServiceRoutingStyle RoutingStyle;
+               internal SoapBindingUse          Use;
+               internal string                  WebServiceName;
+               internal string                  WebServiceNamespace;
+               internal string                  BindingLocation;
+               internal string                  BindingName;
+               internal string                  BindingNamespace;
+
+               // We only use this to avoid creating tons of arrays that are barely used.
+               internal static XmlMembersMapping [] SingleMembersMapping = new XmlMembersMapping [1];
+               
+               void GetTypeAttributes (Type t)
+               {
+                       object [] o;
+
+                       o = t.GetCustomAttributes (typeof (WebServiceBindingAttribute), false);
+                       if (o.Length != 1)
+                               throw new Exception ("Expected WebServiceBindingAttribute on "+ t.Name);
+                       WebServiceBindingAttribute b = (WebServiceBindingAttribute) o [0];
+                       BindingLocation = b.Location;
+                       BindingName = b.Name;
+                       BindingNamespace = b.Namespace;
+
+                       o = t.GetCustomAttributes (typeof (WebService), false);
+                       if (o.Length == 1){
+                               WebServiceAttribute a = (WebServiceAttribute) o [0];
+
+                               WebServiceName = a.Name;
+                               WebServiceNamespace = a.Namespace;
+                       } else {
+                               WebServiceName = t.Name;
+                               WebServiceNamespace = WebServiceAttribute.DefaultNamespace;
+                       }
+
+                       o = t.GetCustomAttributes (typeof (SoapDocumentServiceAttribute), false);
+                       if (o.Length == 1){
+                               SoapDocumentServiceAttribute a = (SoapDocumentServiceAttribute) o [0];
+
+                               ParameterStyle = a.ParameterStyle;
+                               RoutingStyle = a.RoutingStyle;
+                               Use = a.Use;
+                       } else {
+                               ParameterStyle = SoapParameterStyle.Wrapped;
+                               RoutingStyle = SoapServiceRoutingStyle.SoapAction;
+                               Use = SoapBindingUse.Literal;
+                       }
+
+                       //
+                       // Some validation
+                       //
+                       o = t.GetCustomAttributes (typeof (SoapRpcServiceAttribute), false);
+                       if (o.Length != 0)
+                               throw new Exception ("We do not support SoapRpcService encoding, Type=" + t.Name);
+               }
+
+               //
+               // Extract all method information
+               //
+               void GetTypeMethods (Type t, XmlReflectionImporter importer)
+               {
+                       MethodInfo [] type_methods = t.GetMethods (BindingFlags.Instance | BindingFlags.Public);
+                       LogicalMethodInfo [] methods = LogicalMethodInfo.Create (type_methods, LogicalMethodTypes.Sync);
+
+                       foreach (LogicalMethodInfo mi in methods){
+                               MethodStubInfo msi = MethodStubInfo.Create (this, mi, importer);
+
+                               if (msi == null)
+                                       continue;
+                               
+                               name_to_method [msi.Name] = msi;
+                       }
+               }
+               
+               internal TypeStubInfo (Type t)
+               {
+                       GetTypeAttributes (t);
+
+                       XmlReflectionImporter importer = new XmlReflectionImporter ();
+                       GetTypeMethods (t, importer);
+               }
+
+               internal MethodStubInfo GetMethod (string name)
+               {
+                       return (MethodStubInfo) name_to_method [name];
+               }
+       }
+       
+       //
+       // Manages 
+       //
+       internal class TypeStubManager {
+               static Hashtable type_to_manager;
+               
+               static TypeStubManager ()
+               {
+                       type_to_manager = new Hashtable ();
+               }
+
+               //
+               // This needs to be thread safe
+               //
+               static internal TypeStubInfo GetTypeStub (Type t)
+               {
+                       TypeStubInfo tm = (TypeStubInfo) type_to_manager [t];
+
+                       if (tm != null)
+                               return tm;
+
+                       lock (typeof (TypeStubInfo)){
+                               tm = (TypeStubInfo) type_to_manager [t];
+
+                               if (tm != null)
+                                       return tm;
+                               
+                               tm = new TypeStubInfo (t);
+                               type_to_manager [t] = tm;
+
+                               return tm;
+                       }
+               }
+       }
+}
index 88f3584174f8dede897c92e675675b784f262abd..8ec654902c172ba01ccf113c8e9cd4fd9d4a6310 100644 (file)
@@ -17,10 +17,6 @@ Notes on the Soap Client
        Url property of it (to point to the right server) and then
        invoking the stubs. 
 
-       The stub will call SoapHttpClientProtocol.Invoke.  Our
-       implementation walks the stack to find the invoker and extract
-       the attributes that control the processing
-
        SoapHttpClientProtocol will create a SoapClientMessage based
        on this information.  The SoapClientMessage class is used to
        pass the information to hooks or extensions in the .NET
@@ -51,41 +47,35 @@ Notes on the Soap Client
 
 * Metadata
 
-       We need to extract various pieces of information from a given
-       MethodInfo.  Currently this is done in CreateMessage, but it
-       should be moved elsewhere as there is plenty more that we will
-       need to extract, and we are currently just passing all that
-       information to SoapClientMessage as internal data.
-
-       This new structure will also keep a cache of the
-       XmlSerializers that we need for encoding the arguments. 
+       Methods.cs extracts class and method information: it basically
+       pulls all the attributes that can be applied to the class and
+       methods, and stores them into TypeStubInfo and MethodStubInfo.
 
-       This should contain information extracted from the method
-       attributes, at least the following play a role:
+       Also, serializers for input and output types are created and
+       stored into the MethodStubInfo.
 
-               SoapDocumentMethodAttribute
-               WebMethodAttribute
+       There is a cache managed by TypeStubManager (it has to be
+       threadsafe, as SoapHttpClientProtocol will call this and will
+       require thread safe semantics). 
 
+       The cache tracks types, and types track their methods.  This
+       information needs to be computed ahead of time, due to the
+       possible name-clash resolution that VisualStudio uses. 
 
 * Current shortcomings and problems.
 
-       * Need to find a list of all attributes that apply to a
-         method.
-
        * Need a cache that maps (type, method-name) to the
          precomputed MethodMetadata.  The type has to be a derived
          class from SoapHttpClientProtocol.
 
-       * Since we know that WebService names are *unique* we can
-         pull the MethodMetadata based on this key, so it would be:
-
-                       (type, unique-name) -> MethodMetadata
+       * We do not support SoapExtensions.
 
-       * We probably need to compute all the MethodMetadata structs
-         in one pass for a type, as the unique-name can not be
-         discovered unless we do a query on all the attributes
-         attached to methods (see the sample at the end)
+       * We do not support extracting the parameter information and
+         pass the result attribute names to the XmlSerializer, as specified in
+         `Customizing SOAP Messages/Customizing the SOAP Message with XML Serialization'
 
+       * We do not pass the SoapClientMessage as we should to any
+         extensions
 
 * Other notes.
 
index b3c5d79033f0bccb38a894fa26bdff7822b85510..67580c4882730e745755fc78c5c3ca2aa6feec69 100644 (file)
@@ -20,8 +20,12 @@ namespace System.Web.Services.Protocols {
                SoapHttpClientProtocol client;\r
                string url;\r
                LogicalMethodInfo client_method;\r
-               SoapDocumentMethodAttribute sma;\r
-               object [] parameters;\r
+               internal MethodStubInfo MethodStubInfo;\r
+\r
+               //\r
+               // Expose this one internally\r
+               //\r
+               internal object [] Parameters;\r
                #endregion\r
 \r
                #region Constructors\r
@@ -29,14 +33,13 @@ namespace System.Web.Services.Protocols {
                //\r
                // Constructs the SoapClientMessage\r
                //\r
-               internal SoapClientMessage (SoapHttpClientProtocol client, SoapDocumentMethodAttribute sma,\r
-                                           LogicalMethodInfo client_method, bool one_way, string url, object [] parameters)\r
+               internal SoapClientMessage (SoapHttpClientProtocol client, MethodStubInfo msi, string url, object [] parameters)\r
                {\r
-                       this.sma = sma;\r
+                       this.MethodStubInfo = msi;\r
                        this.client = client;\r
                        this.client_method = client_method;\r
                        this.url = url;\r
-                       this.parameters = parameters;\r
+                       Parameters = parameters;\r
                }\r
 \r
                #endregion \r
@@ -44,7 +47,7 @@ namespace System.Web.Services.Protocols {
                #region Properties\r
 \r
                public override string Action {\r
-                       get { return sma.Action; }\r
+                       get { return MethodStubInfo.Action; }\r
                }\r
 \r
                public SoapHttpClientProtocol Client {\r
@@ -56,7 +59,7 @@ namespace System.Web.Services.Protocols {
                }\r
 \r
                public override bool OneWay {\r
-                       get { return sma.OneWay; }\r
+                       get { return MethodStubInfo.OneWay; }\r
                }\r
 \r
                public override string Url {\r
index 19019dbb6ae4b404a9361bde5f691c2e40175a28..a168bcd2c49bdd81baf6bbd81255b408210f2a92 100644 (file)
@@ -22,13 +22,15 @@ using System.Web.Services.Description;
 \r
 namespace System.Web.Services.Protocols {\r
        public class SoapHttpClientProtocol : HttpWebClientProtocol {\r
-\r
+               TypeStubInfo type_info;\r
+               \r
                #region Constructors\r
 \r
                public SoapHttpClientProtocol () \r
                {\r
+                       type_info = TypeStubManager.GetTypeStub (this.GetType ());\r
                }\r
-               \r
+\r
                #endregion // Constructors\r
 \r
                #region Methods\r
@@ -72,69 +74,6 @@ namespace System.Web.Services.Protocols {
                        }\r
                }\r
                \r
-               //\r
-               // The `method_name' should be the name of our invoker, this is only used\r
-               // for sanity checks, nothing else\r
-               //\r
-               [MethodImplAttribute(MethodImplOptions.NoInlining)]\r
-               MethodInfo GetCallerMethod (string method_name)\r
-               {\r
-                       MethodInfo mi;\r
-#if StackFrameWorks\r
-                       StackFrame stack_trace = new StackFrame (5, false);\r
-                       mi = (MethodInfo) stack_frame.GetMethod ();\r
-\r
-#else\r
-                       //\r
-                       // Temporary hack: look for a type which is not this type\r
-                       //\r
-                       StackTrace st = new StackTrace ();\r
-                       mi = null;\r
-                       for (int i = 0; i < st.FrameCount; i++){\r
-                               StackFrame sf = st.GetFrame (i);\r
-                               mi = (MethodInfo) sf.GetMethod ();\r
-                               if (mi.DeclaringType != typeof (SoapHttpClientProtocol))\r
-                                       break;\r
-                       }\r
-#endif\r
-                       //\r
-                       // A few sanity checks, just in case the code moves around later\r
-                       //\r
-                       if (!mi.DeclaringType.IsSubclassOf (typeof (System.Web.Services.Protocols.SoapHttpClientProtocol)))\r
-                               throw new Exception ("We are pointing to the wrong method (T=" + mi.DeclaringType + ")");\r
-\r
-                       if (mi.DeclaringType == typeof (System.Web.Services.Protocols.SoapHttpClientProtocol))\r
-                               throw new Exception ("We are pointing to the wrong method (we are pointing to our Invoke)");\r
-\r
-                       if (mi.Name != method_name)\r
-                               throw new Exception ("The method we point to is: " + mi.Name);\r
-\r
-                       return mi;\r
-               }\r
-               \r
-               [MethodImplAttribute(MethodImplOptions.NoInlining)]\r
-               SoapClientMessage CreateMessage (string method_name, object [] parameters)\r
-               {\r
-                       MethodInfo mi = GetCallerMethod (method_name);\r
-                       object [] attributes = mi.GetCustomAttributes (typeof (System.Web.Services.Protocols.SoapDocumentMethodAttribute), false);\r
-                       SoapDocumentMethodAttribute sma = (SoapDocumentMethodAttribute) attributes [0];\r
-\r
-                       Console.WriteLine ("SMAA:    " + sma.Action);\r
-                       Console.WriteLine ("Binding: " + sma.Binding);\r
-                       Console.WriteLine ("OneWay:  " + sma.OneWay);\r
-                       Console.WriteLine ("PStyle:  " + sma.ParameterStyle);\r
-                       Console.WriteLine ("REN:     " + sma.RequestElementName);\r
-                       Console.WriteLine ("REN:     " + sma.RequestElementName);\r
-\r
-                       if (sma.Use != SoapBindingUse.Literal)\r
-                               throw new Exception ("Soap Section 5 Encoding not supported");\r
-                       \r
-                       SoapClientMessage message = new SoapClientMessage (\r
-                               this, sma, new LogicalMethodInfo (mi), sma.OneWay, Url, parameters);\r
-\r
-                       return message;\r
-               }\r
-\r
                const string soap_envelope = "http://schemas.xmlsoap.org/soap/envelope/";\r
                \r
                void WriteSoapEnvelope (XmlTextWriter xtw)\r
@@ -146,7 +85,7 @@ namespace System.Web.Services.Protocols {
                        xtw.WriteAttributeString ("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");\r
                }\r
                \r
-               void SendMessage (WebRequest request, SoapClientMessage message)\r
+               void SendRequest (WebRequest request, SoapClientMessage message)\r
                {\r
                        WebHeaderCollection headers = request.Headers;\r
                        headers.Add ("SOAPAction", message.Action);\r
@@ -156,28 +95,105 @@ namespace System.Web.Services.Protocols {
                        using (Stream s = request.GetRequestStream ()){\r
                                // serialize arguments\r
 \r
-                               XmlTextWriter xtw = new XmlTextWriter (s, Encoding.UTF8);\r
+                               // What a waste of UTF8encoders, but it has to be thread safe.\r
+                               \r
+                               XmlTextWriter xtw = new XmlTextWriter (s, new UTF8Encoding (false));\r
+                               xtw.Formatting = Formatting.Indented;\r
                                WriteSoapEnvelope (xtw);\r
                                xtw.WriteStartElement ("soap", "Body", soap_envelope);\r
-                               \r
-                               // Serialize arguments here\r
-                               \r
+\r
+                               // Serialize arguments.\r
+                               message.MethodStubInfo.RequestSerializer.Serialize (xtw, message.Parameters);\r
                                xtw.WriteEndElement ();\r
                                xtw.WriteEndElement ();\r
+                               \r
                                xtw.Flush ();\r
                                xtw.Close ();\r
                         }\r
                }\r
+\r
+               void GetContentTypeProperties (string cts, out string encoding, out string content_type)\r
+               {\r
+                       encoding = "utf-8";\r
+                       int start = 0;\r
+                       int idx = cts.IndexOf (';');\r
+                       if (idx == -1)\r
+                               encoding = cts;\r
+                       content_type = cts.Substring (0, idx);\r
+                       for (start = idx + 1; idx != -1;){\r
+                               idx = cts.IndexOf (";", start);\r
+                               string body;\r
+                               if (idx == -1)\r
+                                       body = cts.Substring (start);\r
+                               else {\r
+                                       body = cts.Substring (start, idx);\r
+                                       start = idx + 1;\r
+                               }\r
+                               if (body.StartsWith ("charset=")){\r
+                                       encoding = body.Substring (8);\r
+                               }\r
+                       }\r
+               }\r
                \r
-               [MethodImplAttribute(MethodImplOptions.NoInlining)]\r
-               protected object[] Invoke (string method_name, object[] parameters)\r
+               //\r
+               // TODO:\r
+               //    Handle other web responses (multi-output?)\r
+               //    \r
+               object [] ReceiveResponse (WebResponse response, SoapClientMessage message)\r
                {\r
-                       SoapClientMessage message = CreateMessage (method_name, parameters);\r
-                       WebRequest request = GetWebRequest (uri);\r
+                       HttpWebResponse http_response = (HttpWebResponse) response;\r
+                       HttpStatusCode code = http_response.StatusCode;\r
+                       MethodStubInfo msi = message.MethodStubInfo;\r
                        \r
-                       SendMessage (request, message);\r
+                       if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK))\r
+                               throw new Exception ("Return code was: " + http_response.StatusCode);\r
+\r
+                       //\r
+                       // Remove optional encoding\r
+                       //\r
+                       string content_type, encoding_name;\r
+                       GetContentTypeProperties (response.ContentType, out encoding_name, out content_type);\r
+\r
+                       if (content_type != "text/xml")\r
+                               throw new Exception ("Return value is not XML: " + content_type);\r
+\r
+                       Encoding encoding = Encoding.GetEncoding (encoding_name);\r
+                       Stream stream = response.GetResponseStream ();\r
+                       StreamReader reader = new StreamReader (stream, encoding, false);\r
+                       XmlTextReader xml_reader = new XmlTextReader (reader);\r
+\r
+                       //\r
+                       // Handle faults somewhere\r
+                       //\r
+                       xml_reader.MoveToContent ();\r
+                       xml_reader.ReadStartElement ("Envelope", soap_envelope);\r
+                       xml_reader.MoveToContent ();\r
+                       xml_reader.ReadStartElement ("Body", soap_envelope);\r
+\r
+                       xml_reader.MoveToContent ();\r
+                       xml_reader.ReadStartElement (msi.ResponseName, msi.ResponseNamespace);\r
+\r
+                       object [] ret = (object []) msi.ResponseSerializer.Deserialize (xml_reader);\r
+\r
+                       Console.WriteLine ("Returned array elements: " + ret.Length);\r
+                       for (int i = 0; i < ret.Length; i++){\r
+                               Console.WriteLine ("Value-{0}: {1}", i, ret [i]);\r
+                       }\r
+                       return (object []) ret;\r
+               }\r
+               \r
+               protected object[] Invoke (string method_name, object[] parameters)\r
+               {\r
+                       MethodStubInfo msi = type_info.GetMethod (method_name);\r
                        \r
-                       return null;\r
+                       SoapClientMessage message = new SoapClientMessage (\r
+                               this, msi, Url, parameters);\r
+\r
+                       WebRequest request = GetWebRequest (uri);\r
+                       SendRequest (request, message);\r
+\r
+                       WebResponse response = request.GetResponse ();\r
+                       return ReceiveResponse (response, message);\r
                }\r
 \r
                #endregion // Methods\r
index 5371d9fc94c23f92f0e0ccb75baabf2fa5b372c2..e3f02a8dd2ae8045eb8d76a6451142ef1f07fb8a 100644 (file)
@@ -77,6 +77,7 @@ System.Web.Services.Description/SoapProtocolImporter.cs
 System.Web.Services.Description/SoapProtocolReflector.cs
 System.Web.Services.Description/SoapTransportImporter.cs
 System.Web.Services.Description/Types.cs
+System.Web.Services.Protocols/Methods.cs
 System.Web.Services.Protocols/AnyReturnReader.cs
 System.Web.Services.Protocols/HtmlFormParameterReader.cs
 System.Web.Services.Protocols/HtmlFormParameterWriter.cs