First set of attempts to do RPC, but I need to prefix the method name only,
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / SoapHttpClientProtocol.cs
1 // \r
2 // System.Web.Services.Protocols.SoapHttpClientProtocol.cs\r
3 //\r
4 // Author:\r
5 //   Tim Coleman (tim@timcoleman.com)\r
6 //   Miguel de Icaza (miguel@ximian.com)\r
7 //\r
8 // Copyright (C) Tim Coleman, 2002\r
9 // Copyright (C) Ximian, Inc, 2003\r
10 //\r
11 \r
12 using System.IO;\r
13 using System.Net;\r
14 using System.Web;\r
15 using System.Xml;\r
16 using System.Text;\r
17 using System.Reflection;\r
18 using System.Web.Services;\r
19 using System.Diagnostics;\r
20 using System.Runtime.CompilerServices;\r
21 using System.Web.Services.Description;\r
22 using System.Xml.Serialization;\r
23 namespace System.Web.Services.Protocols {\r
24         public class SoapHttpClientProtocol : HttpWebClientProtocol {\r
25                 TypeStubInfo type_info;\r
26                 \r
27                 #region Constructors\r
28 \r
29                 public SoapHttpClientProtocol () \r
30                 {\r
31                         type_info = TypeStubManager.GetTypeStub (this.GetType ());\r
32                 }\r
33 \r
34                 #endregion // Constructors\r
35 \r
36                 #region Methods\r
37 \r
38                 [MonoTODO]\r
39                 protected IAsyncResult BeginInvoke (string methodName, object[] parameters, AsyncCallback callback, object asyncState)\r
40                 {\r
41                         throw new NotImplementedException ();\r
42                 }\r
43 \r
44                 [MonoTODO]\r
45                 public void Discover ()\r
46                 {\r
47                         throw new NotImplementedException ();\r
48                 }\r
49 \r
50                 [MonoTODO]\r
51                 protected object[] EndInvoke (IAsyncResult asyncResult)\r
52                 {\r
53                         throw new NotImplementedException ();\r
54                 }\r
55 \r
56                 protected override WebRequest GetWebRequest (Uri uri)\r
57                 {\r
58                         WebRequest request = WebRequest.Create (uri);\r
59                         request.Method = "POST";\r
60 \r
61                         return request;\r
62                 }\r
63 \r
64                 //\r
65                 // Just for debugging\r
66                 //\r
67                 void DumpStackFrames ()\r
68                 {\r
69                         StackTrace st = new StackTrace ();\r
70 \r
71                         for (int i = 0; i < st.FrameCount; i++){\r
72                                 StackFrame sf = st.GetFrame (i);\r
73                                 Console.WriteLine ("At frame: {0} {1}", i, sf.GetMethod ().Name);\r
74                         }\r
75                 }\r
76                 \r
77                 const string soap_envelope = "http://schemas.xmlsoap.org/soap/envelope/";\r
78                 \r
79                 void WriteSoapEnvelope (XmlTextWriter xtw)\r
80                 {\r
81                         xtw.WriteStartDocument ();\r
82                         \r
83                         xtw.WriteStartElement ("soap", "Envelope", soap_envelope);\r
84                         xtw.WriteAttributeString ("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");\r
85                         xtw.WriteAttributeString ("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");\r
86                 }\r
87                 \r
88                 void SendRequest (WebRequest request, SoapClientMessage message)\r
89                 {\r
90                         WebHeaderCollection headers = request.Headers;\r
91                         headers.Add ("SOAPAction", message.Action);\r
92 \r
93                         request.ContentType = message.ContentType + "; charset=utf-8";\r
94 \r
95                         using (Stream s = request.GetRequestStream ()){\r
96                                 // serialize arguments\r
97 \r
98                                 // What a waste of UTF8encoders, but it has to be thread safe.\r
99                                 \r
100                                 XmlTextWriter xtw = new XmlTextWriter (s, new UTF8Encoding (false));\r
101                                 xtw.Formatting = Formatting.Indented;\r
102                                 WriteSoapEnvelope (xtw);\r
103                                 xtw.WriteStartElement ("soap", "Body", soap_envelope);\r
104 \r
105                                 // Serialize arguments.\r
106                                 message.MethodStubInfo.RequestSerializer.Serialize (xtw, message.Parameters);\r
107                                 xtw.WriteEndElement ();\r
108                                 xtw.WriteEndElement ();\r
109                                 \r
110                                 xtw.Flush ();\r
111                                 xtw.Close ();\r
112                          }\r
113                 }\r
114 \r
115                 void GetContentTypeProperties (string cts, out string encoding, out string content_type)\r
116                 {\r
117                         encoding = "utf-8";\r
118                         int start = 0;\r
119                         int idx = cts.IndexOf (';');\r
120                         if (idx == -1)\r
121                                 encoding = cts;\r
122                         content_type = cts.Substring (0, idx);\r
123                         for (start = idx + 1; idx != -1;){\r
124                                 idx = cts.IndexOf (";", start);\r
125                                 string body;\r
126                                 if (idx == -1)\r
127                                         body = cts.Substring (start);\r
128                                 else {\r
129                                         body = cts.Substring (start, idx);\r
130                                         start = idx + 1;\r
131                                 }\r
132                                 if (body.StartsWith ("charset=")){\r
133                                         encoding = body.Substring (8);\r
134                                 }\r
135                         }\r
136                 }\r
137                 \r
138                 //\r
139                 // TODO:\r
140                 //    Handle other web responses (multi-output?)\r
141                 //    \r
142                 object [] ReceiveResponse (WebResponse response, SoapClientMessage message)\r
143                 {\r
144                         HttpWebResponse http_response = (HttpWebResponse) response;\r
145                         HttpStatusCode code = http_response.StatusCode;\r
146                         MethodStubInfo msi = message.MethodStubInfo;\r
147                         \r
148                         if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK))\r
149                                 throw new Exception ("Return code was: " + http_response.StatusCode);\r
150 \r
151                         //\r
152                         // Remove optional encoding\r
153                         //\r
154                         string content_type, encoding_name;\r
155                         GetContentTypeProperties (response.ContentType, out encoding_name, out content_type);\r
156 \r
157                         if (content_type != "text/xml")\r
158                                 throw new Exception ("Return value is not XML: " + content_type);\r
159 \r
160                         Encoding encoding = Encoding.GetEncoding (encoding_name);\r
161                         Stream stream = response.GetResponseStream ();\r
162                         StreamReader reader = new StreamReader (stream, encoding, false);\r
163                         XmlTextReader xml_reader = new XmlTextReader (reader);\r
164 \r
165                         //\r
166                         // Handle faults/errors somewhere\r
167                         //\r
168                         xml_reader.MoveToContent ();\r
169                         xml_reader.ReadStartElement ("Envelope", soap_envelope);\r
170                         xml_reader.MoveToContent ();\r
171                         xml_reader.ReadStartElement ("Body", soap_envelope);\r
172 \r
173                         object [] ret = (object []) msi.ResponseSerializer.Deserialize (xml_reader);\r
174 \r
175                         return (object []) ret;\r
176                 }\r
177 \r
178                 protected object[] Invoke (string method_name, object[] parameters)\r
179                 {\r
180                         MethodStubInfo msi = type_info.GetMethod (method_name);\r
181 \r
182                         SoapClientMessage message = new SoapClientMessage (\r
183                                 this, msi, Url, parameters);\r
184 \r
185                         WebRequest request = GetWebRequest (uri);\r
186                         SendRequest (request, message);\r
187 \r
188                         WebResponse response = request.GetResponse ();\r
189                         return ReceiveResponse (response, message);\r
190                 }\r
191 \r
192                 #endregion // Methods\r
193         }\r
194 }\r