2 // System.Web.Services.Protocols.SoapHttpClientProtocol.cs
\r
5 // Tim Coleman (tim@timcoleman.com)
\r
6 // Miguel de Icaza (miguel@ximian.com)
\r
8 // Copyright (C) Tim Coleman, 2002
\r
9 // Copyright (C) Ximian, Inc, 2003
\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
27 #region Constructors
\r
29 public SoapHttpClientProtocol ()
\r
31 type_info = TypeStubManager.GetTypeStub (this.GetType ());
\r
34 #endregion // Constructors
\r
39 protected IAsyncResult BeginInvoke (string methodName, object[] parameters, AsyncCallback callback, object asyncState)
\r
41 throw new NotImplementedException ();
\r
45 public void Discover ()
\r
47 throw new NotImplementedException ();
\r
51 protected object[] EndInvoke (IAsyncResult asyncResult)
\r
53 throw new NotImplementedException ();
\r
56 protected override WebRequest GetWebRequest (Uri uri)
\r
58 WebRequest request = WebRequest.Create (uri);
\r
59 request.Method = "POST";
\r
65 // Just for debugging
\r
67 void DumpStackFrames ()
\r
69 StackTrace st = new StackTrace ();
\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
77 const string soap_envelope = "http://schemas.xmlsoap.org/soap/envelope/";
\r
79 void WriteSoapEnvelope (XmlTextWriter xtw)
\r
81 xtw.WriteStartDocument ();
\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
88 void SendRequest (WebRequest request, SoapClientMessage message)
\r
90 WebHeaderCollection headers = request.Headers;
\r
91 headers.Add ("SOAPAction", message.Action);
\r
93 request.ContentType = message.ContentType + "; charset=utf-8";
\r
95 using (Stream s = request.GetRequestStream ()){
\r
96 // serialize arguments
\r
98 // What a waste of UTF8encoders, but it has to be thread safe.
\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
105 // Serialize arguments.
\r
106 message.MethodStubInfo.RequestSerializer.Serialize (xtw, message.Parameters);
\r
107 xtw.WriteEndElement ();
\r
108 xtw.WriteEndElement ();
\r
115 void GetContentTypeProperties (string cts, out string encoding, out string content_type)
\r
117 encoding = "utf-8";
\r
119 int idx = cts.IndexOf (';');
\r
122 content_type = cts.Substring (0, idx);
\r
123 for (start = idx + 1; idx != -1;){
\r
124 idx = cts.IndexOf (";", start);
\r
127 body = cts.Substring (start);
\r
129 body = cts.Substring (start, idx);
\r
132 if (body.StartsWith ("charset=")){
\r
133 encoding = body.Substring (8);
\r
140 // Handle other web responses (multi-output?)
\r
142 object [] ReceiveResponse (WebResponse response, SoapClientMessage message)
\r
144 HttpWebResponse http_response = (HttpWebResponse) response;
\r
145 HttpStatusCode code = http_response.StatusCode;
\r
146 MethodStubInfo msi = message.MethodStubInfo;
\r
148 if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK || code == HttpStatusCode.InternalServerError))
\r
149 throw new Exception ("Return code was: " + http_response.StatusCode);
\r
152 // Remove optional encoding
\r
155 string content_type, encoding_name;
\r
156 GetContentTypeProperties (response.ContentType, out encoding_name, out content_type);
\r
158 if (content_type != "text/xml")
\r
159 throw new Exception ("Return value is not XML: " + content_type);
\r
161 Encoding encoding = Encoding.GetEncoding (encoding_name);
\r
162 Stream stream = response.GetResponseStream ();
\r
163 StreamReader reader = new StreamReader (stream, encoding, false);
\r
164 XmlTextReader xml_reader = new XmlTextReader (reader);
\r
166 xml_reader.MoveToContent ();
\r
167 xml_reader.ReadStartElement ("Envelope", soap_envelope);
\r
168 xml_reader.MoveToContent ();
\r
169 xml_reader.ReadStartElement ("Body", soap_envelope);
\r
171 if (code != HttpStatusCode.InternalServerError)
\r
173 object [] ret = (object []) msi.ResponseSerializer.Deserialize (xml_reader);
\r
174 return (object []) ret;
\r
178 Fault fault = (Fault) msi.FaultSerializer.Deserialize (xml_reader);
\r
179 throw new SoapException (fault.faultstring, fault.faultcode, fault.faultactor, fault.detail);
\r
183 protected object[] Invoke (string method_name, object[] parameters)
\r
185 MethodStubInfo msi = type_info.GetMethod (method_name);
\r
187 SoapClientMessage message = new SoapClientMessage (
\r
188 this, msi, Url, parameters);
\r
190 WebResponse response;
\r
193 WebRequest request = GetWebRequest (uri);
\r
194 SendRequest (request, message);
\r
195 response = request.GetResponse ();
\r
197 catch (WebException ex)
\r
199 response = ex.Response;
\r
200 HttpWebResponse http_response = response as HttpWebResponse;
\r
201 if (http_response == null || http_response.StatusCode != HttpStatusCode.InternalServerError)
\r
205 return ReceiveResponse (response, message);
\r
208 #endregion // Methods
\r