SoapHttpClientProtocol.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  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. return base.GetWebRequest (uri);
  50. }
  51. //
  52. // Just for debugging
  53. //
  54. void DumpStackFrames ()
  55. {
  56. StackTrace st = new StackTrace ();
  57. for (int i = 0; i < st.FrameCount; i++){
  58. StackFrame sf = st.GetFrame (i);
  59. Console.WriteLine ("At frame: {0} {1}", i, sf.GetMethod ().Name);
  60. }
  61. }
  62. const string soap_envelope = "http://schemas.xmlsoap.org/soap/envelope/";
  63. void WriteSoapEnvelope (XmlTextWriter xtw, SoapHeaderCollection headers)
  64. {
  65. xtw.WriteStartDocument ();
  66. xtw.WriteStartElement ("soap", "Envelope", soap_envelope);
  67. xtw.WriteAttributeString ("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
  68. xtw.WriteAttributeString ("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
  69. foreach (SoapHeader header in headers) {
  70. XmlSerializer ser = type_info.GetCommonSerializer (header.GetType());
  71. xtw.WriteStartElement ("soap", "Header", soap_envelope);
  72. ser.Serialize (xtw, header);
  73. xtw.WriteEndElement ();
  74. }
  75. }
  76. void SendRequest (WebRequest request, SoapClientMessage message)
  77. {
  78. request.Method = "POST";
  79. WebHeaderCollection headers = request.Headers;
  80. headers.Add ("SOAPAction", message.Action);
  81. request.ContentType = message.ContentType + "; charset=utf-8";
  82. using (Stream s = request.GetRequestStream ()){
  83. // serialize arguments
  84. // What a waste of UTF8encoders, but it has to be thread safe.
  85. XmlTextWriter xtw = new XmlTextWriter (s, new UTF8Encoding (false));
  86. xtw.Formatting = Formatting.Indented;
  87. WriteSoapEnvelope (xtw, message.Headers);
  88. xtw.WriteStartElement ("soap", "Body", soap_envelope);
  89. // Serialize arguments.
  90. message.MethodStubInfo.RequestSerializer.Serialize (xtw, message.Parameters);
  91. xtw.WriteEndElement ();
  92. xtw.WriteEndElement ();
  93. xtw.Flush ();
  94. xtw.Close ();
  95. }
  96. }
  97. void GetContentTypeProperties (string cts, out string encoding, out string content_type)
  98. {
  99. encoding = "utf-8";
  100. int start = 0;
  101. int idx = cts.IndexOf (';');
  102. if (idx == -1)
  103. encoding = cts;
  104. content_type = cts.Substring (0, idx);
  105. for (start = idx + 1; idx != -1;){
  106. idx = cts.IndexOf (";", start);
  107. string body;
  108. if (idx == -1)
  109. body = cts.Substring (start);
  110. else {
  111. body = cts.Substring (start, idx);
  112. start = idx + 1;
  113. }
  114. if (body.StartsWith ("charset=")){
  115. encoding = body.Substring (8);
  116. }
  117. }
  118. }
  119. //
  120. // TODO:
  121. // Handle other web responses (multi-output?)
  122. //
  123. object [] ReceiveResponse (WebResponse response, SoapClientMessage message)
  124. {
  125. HttpWebResponse http_response = (HttpWebResponse) response;
  126. HttpStatusCode code = http_response.StatusCode;
  127. MethodStubInfo msi = message.MethodStubInfo;
  128. if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK || code == HttpStatusCode.InternalServerError))
  129. throw new Exception ("Return code was: " + http_response.StatusCode);
  130. //
  131. // Remove optional encoding
  132. //
  133. string content_type, encoding_name;
  134. GetContentTypeProperties (response.ContentType, out encoding_name, out content_type);
  135. if (content_type != "text/xml")
  136. throw new Exception ("Return value is not XML: " + content_type);
  137. Encoding encoding = Encoding.GetEncoding (encoding_name);
  138. Stream stream = response.GetResponseStream ();
  139. StreamReader reader = new StreamReader (stream, encoding, false);
  140. XmlTextReader xml_reader = new XmlTextReader (reader);
  141. xml_reader.MoveToContent ();
  142. xml_reader.ReadStartElement ("Envelope", soap_envelope);
  143. xml_reader.MoveToContent ();
  144. xml_reader.ReadStartElement ("Body", soap_envelope);
  145. if (code != HttpStatusCode.InternalServerError)
  146. {
  147. object [] ret = (object []) msi.ResponseSerializer.Deserialize (xml_reader);
  148. return (object []) ret;
  149. }
  150. else
  151. {
  152. Fault fault = (Fault) type_info.FaultSerializer.Deserialize (xml_reader);
  153. throw new SoapException (fault.faultstring, fault.faultcode, fault.faultactor, fault.detail);
  154. }
  155. }
  156. protected object[] Invoke (string method_name, object[] parameters)
  157. {
  158. MethodStubInfo msi = type_info.GetMethod (method_name);
  159. SoapClientMessage message = new SoapClientMessage (
  160. this, msi, Url, parameters);
  161. WebResponse response;
  162. try
  163. {
  164. WebRequest request = GetWebRequest (uri);
  165. SendRequest (request, message);
  166. response = GetWebResponse (request);
  167. }
  168. catch (WebException ex)
  169. {
  170. response = ex.Response;
  171. HttpWebResponse http_response = response as HttpWebResponse;
  172. if (http_response == null || http_response.StatusCode != HttpStatusCode.InternalServerError)
  173. throw ex;
  174. }
  175. return ReceiveResponse (response, message);
  176. }
  177. #endregion // Methods
  178. }
  179. }