* SoapHttpClientProtocol.cs, HttpSoapWebServiceHandler.cs, Methods.cs:
[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 //   Lluis Sanchez Gual (lluis@ximian.com)\r
8 //\r
9 // Copyright (C) Tim Coleman, 2002\r
10 // Copyright (C) Ximian, Inc, 2003\r
11 //\r
12 \r
13 using System.IO;\r
14 using System.Net;\r
15 using System.Web;\r
16 using System.Xml;\r
17 using System.Text;\r
18 using System.Reflection;\r
19 using System.Web.Services;\r
20 using System.Diagnostics;\r
21 using System.Runtime.CompilerServices;\r
22 using System.Web.Services.Description;\r
23 using System.Xml.Serialization;\r
24 using System.Xml.Schema;\r
25 using System.Collections;\r
26 \r
27 namespace System.Web.Services.Protocols {\r
28         public class SoapHttpClientProtocol : HttpWebClientProtocol {\r
29                 TypeStubInfo type_info;\r
30                 \r
31                 #region Constructors\r
32 \r
33                 public SoapHttpClientProtocol () \r
34                 {\r
35                         type_info = TypeStubManager.GetTypeStub (this.GetType ());\r
36                 }\r
37 \r
38                 #endregion // Constructors\r
39 \r
40                 #region Methods\r
41 \r
42                 [MonoTODO]\r
43                 protected IAsyncResult BeginInvoke (string methodName, object[] parameters, AsyncCallback callback, object asyncState)\r
44                 {\r
45                         throw new NotImplementedException ();\r
46                 }\r
47 \r
48                 [MonoTODO]\r
49                 public void Discover ()\r
50                 {\r
51                         throw new NotImplementedException ();\r
52                 }\r
53 \r
54                 [MonoTODO]\r
55                 protected object[] EndInvoke (IAsyncResult asyncResult)\r
56                 {\r
57                         throw new NotImplementedException ();\r
58                 }\r
59 \r
60                 protected override WebRequest GetWebRequest (Uri uri)\r
61                 {\r
62                         return base.GetWebRequest (uri);\r
63                 }\r
64 \r
65                 //\r
66                 // Just for debugging\r
67                 //\r
68                 void DumpStackFrames ()\r
69                 {\r
70                         StackTrace st = new StackTrace ();\r
71 \r
72                         for (int i = 0; i < st.FrameCount; i++){\r
73                                 StackFrame sf = st.GetFrame (i);\r
74                                 Console.WriteLine ("At frame: {0} {1}", i, sf.GetMethod ().Name);\r
75                         }\r
76                 }\r
77                 \r
78                 void SendRequest (WebRequest request, SoapClientMessage message, SoapExtension[] extensions)\r
79                 {\r
80                         message.CollectHeaders (this, message.MethodStubInfo.Headers, SoapHeaderDirection.In);\r
81 \r
82                         request.Method = "POST";\r
83                         WebHeaderCollection headers = request.Headers;\r
84                         headers.Add ("SOAPAction", message.Action);\r
85 \r
86                         request.ContentType = message.ContentType + "; charset=utf-8";\r
87 \r
88                         Stream s = request.GetRequestStream ();\r
89                         using (s) {\r
90 \r
91                                 if (extensions != null) {\r
92                                         s = SoapExtension.ExecuteChainStream (extensions, s);\r
93                                         message.SetStage (SoapMessageStage.BeforeSerialize);\r
94                                         SoapExtension.ExecuteProcessMessage (extensions, message, true);
95                                 }
96 \r
97                                 // What a waste of UTF8encoders, but it has to be thread safe.\r
98                                 XmlTextWriter xtw = new XmlTextWriter (s, new UTF8Encoding (false));\r
99                                 xtw.Formatting = Formatting.Indented;\r
100 \r
101                                 WebServiceHelper.WriteSoapMessage (xtw, type_info, message.MethodStubInfo.RequestSerializer, message.Parameters, message.Headers);\r
102 \r
103                                 if (extensions != null) {\r
104                                         message.SetStage (SoapMessageStage.AfterSerialize);\r
105                                         SoapExtension.ExecuteProcessMessage (extensions, message, true);
106                                 }
107 \r
108                                 xtw.Flush ();\r
109                                 xtw.Close ();\r
110                          }\r
111                 }\r
112 \r
113 \r
114                 //\r
115                 // TODO:\r
116                 //    Handle other web responses (multi-output?)\r
117                 //    \r
118                 object [] ReceiveResponse (WebResponse response, SoapClientMessage message, SoapExtension[] extensions)\r
119                 {\r
120                         HttpWebResponse http_response = (HttpWebResponse) response;\r
121                         HttpStatusCode code = http_response.StatusCode;\r
122                         MethodStubInfo msi = message.MethodStubInfo;\r
123 \r
124                         if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK || code == HttpStatusCode.InternalServerError))\r
125                                 throw new Exception ("Return code was: " + http_response.StatusCode);\r
126 \r
127                         //\r
128                         // Remove optional encoding\r
129                         //\r
130                         Encoding encoding = WebServiceHelper.GetContentEncoding (response.ContentType);\r
131 \r
132                         Stream stream = response.GetResponseStream ();\r
133 \r
134                         if (extensions != null) {\r
135                                 stream = SoapExtension.ExecuteChainStream (extensions, stream);\r
136                                 message.SetStage (SoapMessageStage.BeforeDeserialize);\r
137                                 SoapExtension.ExecuteProcessMessage (extensions, message, false);
138                         }
139                         \r
140                         // Deserialize the response\r
141 \r
142                         StreamReader reader = new StreamReader (stream, encoding, false);\r
143                         XmlTextReader xml_reader = new XmlTextReader (reader);\r
144 \r
145                         bool isSuccessful = (code != HttpStatusCode.InternalServerError);\r
146                         SoapHeaderCollection headers;\r
147                         object content;\r
148 \r
149                         if (isSuccessful) {\r
150                                 WebServiceHelper.ReadSoapMessage (xml_reader, type_info, msi.ResponseSerializer, out content, out headers);\r
151                                 message.OutParameters = (object[]) content;\r
152                         }\r
153                         else {\r
154                                 WebServiceHelper.ReadSoapMessage (xml_reader, type_info, type_info.FaultSerializer, out content, out headers);\r
155                                 Fault fault = (Fault) content;\r
156                                 SoapException ex = new SoapException (fault.faultstring, fault.faultcode, fault.faultactor, fault.detail);\r
157                                 message.SetException (ex);\r
158                         }\r
159 \r
160                         message.SetHeaders (headers);\r
161                         message.UpdateHeaderValues (this, message.MethodStubInfo.Headers);\r
162 \r
163                         if (extensions != null) {\r
164                                 message.SetStage (SoapMessageStage.AfterDeserialize);\r
165                                 SoapExtension.ExecuteProcessMessage (extensions, message, false);
166                         }
167 \r
168                         if (isSuccessful)\r
169                                 return message.OutParameters;\r
170                         else\r
171                                 throw message.Exception;\r
172                 }\r
173 \r
174                 protected object[] Invoke (string method_name, object[] parameters)\r
175                 {\r
176                         MethodStubInfo msi = type_info.GetMethod (method_name);\r
177                         \r
178                         SoapClientMessage message = new SoapClientMessage (\r
179                                 this, msi, Url, parameters);\r
180 \r
181                         SoapExtension[] extensions = SoapExtension.CreateExtensionChain (type_info.SoapExtensions[0], msi.SoapExtensions, type_info.SoapExtensions[1]);\r
182 \r
183                         WebResponse response;\r
184                         try\r
185                         {\r
186                                 WebRequest request = GetWebRequest (uri);\r
187                                 SendRequest (request, message, extensions);\r
188                                 response = GetWebResponse (request);\r
189                         }\r
190                         catch (WebException ex)\r
191                         {\r
192                                 response = ex.Response;\r
193                                 HttpWebResponse http_response = response as HttpWebResponse;\r
194                                 if (http_response == null || http_response.StatusCode != HttpStatusCode.InternalServerError)\r
195                                         throw ex;\r
196                         }\r
197 \r
198                         return ReceiveResponse (response, message, extensions);\r
199                 }\r
200 \r
201                 #endregion // Methods\r
202         }\r
203 }\r