SoapHttpClientProtocol.cs 6.1 KB

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