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 return base.GetWebRequest (uri);
\r
62 // Just for debugging
\r
64 void DumpStackFrames ()
\r
66 StackTrace st = new StackTrace ();
\r
68 for (int i = 0; i < st.FrameCount; i++){
\r
69 StackFrame sf = st.GetFrame (i);
\r
70 Console.WriteLine ("At frame: {0} {1}", i, sf.GetMethod ().Name);
\r
74 const string soap_envelope = "http://schemas.xmlsoap.org/soap/envelope/";
\r
76 void WriteSoapEnvelope (XmlTextWriter xtw, SoapHeaderCollection headers)
\r
78 xtw.WriteStartDocument ();
\r
80 xtw.WriteStartElement ("soap", "Envelope", soap_envelope);
\r
81 xtw.WriteAttributeString ("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance");
\r
82 xtw.WriteAttributeString ("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema");
\r
84 foreach (SoapHeader header in headers) {
\r
85 XmlSerializer ser = type_info.GetCommonSerializer (header.GetType());
\r
86 xtw.WriteStartElement ("soap", "Header", soap_envelope);
\r
87 ser.Serialize (xtw, header);
\r
88 xtw.WriteEndElement ();
\r
92 void SendRequest (WebRequest request, SoapClientMessage message)
\r
94 request.Method = "POST";
\r
95 WebHeaderCollection headers = request.Headers;
\r
96 headers.Add ("SOAPAction", message.Action);
\r
98 request.ContentType = message.ContentType + "; charset=utf-8";
\r
100 using (Stream s = request.GetRequestStream ()){
\r
101 // serialize arguments
\r
103 // What a waste of UTF8encoders, but it has to be thread safe.
\r
105 XmlTextWriter xtw = new XmlTextWriter (s, new UTF8Encoding (false));
\r
106 xtw.Formatting = Formatting.Indented;
\r
107 WriteSoapEnvelope (xtw, message.Headers);
\r
108 xtw.WriteStartElement ("soap", "Body", soap_envelope);
\r
110 // Serialize arguments.
\r
111 message.MethodStubInfo.RequestSerializer.Serialize (xtw, message.Parameters);
\r
112 xtw.WriteEndElement ();
\r
113 xtw.WriteEndElement ();
\r
120 void GetContentTypeProperties (string cts, out string encoding, out string content_type)
\r
122 encoding = "utf-8";
\r
124 int idx = cts.IndexOf (';');
\r
127 content_type = cts.Substring (0, idx);
\r
128 for (start = idx + 1; idx != -1;){
\r
129 idx = cts.IndexOf (";", start);
\r
132 body = cts.Substring (start);
\r
134 body = cts.Substring (start, idx);
\r
137 if (body.StartsWith ("charset=")){
\r
138 encoding = body.Substring (8);
\r
145 // Handle other web responses (multi-output?)
\r
147 object [] ReceiveResponse (WebResponse response, SoapClientMessage message)
\r
149 HttpWebResponse http_response = (HttpWebResponse) response;
\r
150 HttpStatusCode code = http_response.StatusCode;
\r
151 MethodStubInfo msi = message.MethodStubInfo;
\r
153 if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK || code == HttpStatusCode.InternalServerError))
\r
154 throw new Exception ("Return code was: " + http_response.StatusCode);
\r
157 // Remove optional encoding
\r
160 string content_type, encoding_name;
\r
161 GetContentTypeProperties (response.ContentType, out encoding_name, out content_type);
\r
163 if (content_type != "text/xml")
\r
164 throw new Exception ("Return value is not XML: " + content_type);
\r
166 Encoding encoding = Encoding.GetEncoding (encoding_name);
\r
167 Stream stream = response.GetResponseStream ();
\r
168 StreamReader reader = new StreamReader (stream, encoding, false);
\r
169 XmlTextReader xml_reader = new XmlTextReader (reader);
\r
171 xml_reader.MoveToContent ();
\r
172 xml_reader.ReadStartElement ("Envelope", soap_envelope);
\r
173 xml_reader.MoveToContent ();
\r
174 xml_reader.ReadStartElement ("Body", soap_envelope);
\r
176 if (code != HttpStatusCode.InternalServerError)
\r
178 object [] ret = (object []) msi.ResponseSerializer.Deserialize (xml_reader);
\r
179 return (object []) ret;
\r
183 Fault fault = (Fault) type_info.FaultSerializer.Deserialize (xml_reader);
\r
184 throw new SoapException (fault.faultstring, fault.faultcode, fault.faultactor, fault.detail);
\r
188 protected object[] Invoke (string method_name, object[] parameters)
\r
190 MethodStubInfo msi = type_info.GetMethod (method_name);
\r
192 SoapClientMessage message = new SoapClientMessage (
\r
193 this, msi, Url, parameters);
\r
195 WebResponse response;
\r
198 WebRequest request = GetWebRequest (uri);
\r
199 SendRequest (request, message);
\r
200 response = GetWebResponse (request);
\r
202 catch (WebException ex)
\r
204 response = ex.Response;
\r
205 HttpWebResponse http_response = response as HttpWebResponse;
\r
206 if (http_response == null || http_response.StatusCode != HttpStatusCode.InternalServerError)
\r
210 return ReceiveResponse (response, message);
\r
213 #endregion // Methods
\r