// // TODO: // Handle other web responses (multi-output?) // object [] ReceiveResponse(WebResponse response, SoapClientMessage message, SoapExtension[] extensions) { SoapMethodStubInfo msi = message.MethodStubInfo; HttpWebResponse http_response = response as HttpWebResponse; if (http_response != null) { HttpStatusCode code = http_response.StatusCode; if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK || code == HttpStatusCode.InternalServerError)) { string msg = "The request failed with HTTP status {0}: {1}"; msg = String.Format(msg, (int)code, code); throw new WebException(msg, null, WebExceptionStatus.ProtocolError, http_response); } if (message.OneWay && response.ContentLength <= 0 && (code == HttpStatusCode.Accepted || code == HttpStatusCode.OK)) { return(new object[0]); } } // // Remove optional encoding // string ctype; Encoding encoding = WebServiceHelper.GetContentEncoding(response.ContentType, out ctype); ctype = ctype.ToLower(CultureInfo.InvariantCulture); if ((!message.IsSoap12 || ctype != "application/soap+xml") && ctype != "text/xml") { WebServiceHelper.InvalidOperation( String.Format("Not supported Content-Type in the response: '{0}'", response.ContentType), response, encoding); } message.ContentType = ctype; message.ContentEncoding = encoding.WebName; Stream stream = response.GetResponseStream(); if (extensions != null) { stream = SoapExtension.ExecuteChainStream(extensions, stream); message.SetStage(SoapMessageStage.BeforeDeserialize); SoapExtension.ExecuteProcessMessage(extensions, message, stream, false); } // Deserialize the response SoapHeaderCollection headers; object content; using (StreamReader reader = new StreamReader(stream, encoding, false)) { XmlTextReader xml_reader = new XmlTextReader(reader); WebServiceHelper.ReadSoapMessage(xml_reader, msi, SoapHeaderDirection.Out, message.IsSoap12, out content, out headers); } if (content is Soap12Fault) { SoapException ex = WebServiceHelper.Soap12FaultToSoapException((Soap12Fault)content); message.SetException(ex); } else if (content is Fault) { Fault fault = (Fault)content; SoapException ex = new SoapException(fault.faultstring, fault.faultcode, fault.faultactor, fault.detail); message.SetException(ex); } else { message.OutParameters = (object[])content; } message.SetHeaders(headers); message.UpdateHeaderValues(this, message.MethodStubInfo.Headers); if (extensions != null) { message.SetStage(SoapMessageStage.AfterDeserialize); SoapExtension.ExecuteProcessMessage(extensions, message, stream, false); } if (message.Exception == null) { return(message.OutParameters); } else { throw message.Exception; } }
// // TODO: // Handle other web responses (multi-output?) // object [] ReceiveResponse (WebResponse response, SoapClientMessage message, SoapExtension[] extensions) { SoapMethodStubInfo msi = message.MethodStubInfo; HttpWebResponse http_response = response as HttpWebResponse; if (http_response != null) { HttpStatusCode code = http_response.StatusCode; if (!(code == HttpStatusCode.Accepted || code == HttpStatusCode.OK || code == HttpStatusCode.InternalServerError)) { string msg = "The request failed with HTTP status {0}: {1}"; msg = String.Format (msg, (int) code, code); throw new WebException (msg, null, WebExceptionStatus.ProtocolError, http_response); } if (message.OneWay && response.ContentLength == 0 && (code == HttpStatusCode.Accepted || code == HttpStatusCode.OK)) { return new object[0]; } } // // Remove optional encoding // string ctype; Encoding encoding = WebServiceHelper.GetContentEncoding (response.ContentType, out ctype); if (ctype != "text/xml") WebServiceHelper.InvalidOperation ( "Content is not 'text/xml' but '" + response.ContentType + "'", response, encoding); message.ContentType = ctype; message.ContentEncoding = encoding.WebName; Stream stream = response.GetResponseStream (); if (extensions != null) { stream = SoapExtension.ExecuteChainStream (extensions, stream); message.SetStage (SoapMessageStage.BeforeDeserialize); SoapExtension.ExecuteProcessMessage (extensions, message, false); } // Deserialize the response SoapHeaderCollection headers; object content; using (StreamReader reader = new StreamReader (stream, encoding, false)) { XmlTextReader xml_reader = new XmlTextReader (reader); WebServiceHelper.ReadSoapMessage (xml_reader, type_info, msi.Use, msi.ResponseSerializer, out content, out headers); } if (content is Fault) { Fault fault = (Fault) content; SoapException ex = new SoapException (fault.faultstring, fault.faultcode, fault.faultactor, fault.detail); message.SetException (ex); } else message.OutParameters = (object[]) content; message.SetHeaders (headers); message.UpdateHeaderValues (this, message.MethodStubInfo.Headers); if (extensions != null) { message.SetStage (SoapMessageStage.AfterDeserialize); SoapExtension.ExecuteProcessMessage (extensions, message, false); } if (message.Exception == null) return message.OutParameters; else throw message.Exception; }
object[] ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, bool asyncCall) { SoapClientMethod method = message.Method; // CONSIDER,yannc: use the SoapExtensionStream here as well so we throw exceptions // : if the extension touches stream properties/methods in before deserialize. // note that if there is an error status code then the response might be content-type=text/plain. HttpWebResponse httpResponse = response as HttpWebResponse; int statusCode = httpResponse != null ? (int)httpResponse.StatusCode : -1; if (statusCode >= 300 && statusCode != 500 && statusCode != 400) { throw new WebException(RequestResponseUtils.CreateResponseExceptionString(httpResponse, responseStream), null, WebExceptionStatus.ProtocolError, httpResponse); } message.Headers.Clear(); message.SetStream(responseStream); message.InitExtensionStreamChain(message.initializedExtensions); message.SetStage(SoapMessageStage.BeforeDeserialize); message.ContentType = response.ContentType; message.ContentEncoding = response.Headers[ContentType.ContentEncoding]; message.RunExtensions(message.initializedExtensions); if (method.oneWay && (httpResponse == null || (int)httpResponse.StatusCode != 500)) { return(new object[0]); } // this statusCode check is just so we don't repeat the contentType check we did above if (!ContentType.IsSoap(message.ContentType)) { // special-case 400 since we exempted it above on the off-chance it might be a soap 1.2 sender fault. // based on the content-type, it looks like it's probably just a regular old 400 if (statusCode == 400) { throw new WebException(RequestResponseUtils.CreateResponseExceptionString(httpResponse, responseStream), null, WebExceptionStatus.ProtocolError, httpResponse); } else { throw new InvalidOperationException(Res.GetString(Res.WebResponseContent, message.ContentType, HttpContentType) + "\r\n" + RequestResponseUtils.CreateResponseExceptionString(response, responseStream)); } } Encoding enc = RequestResponseUtils.GetEncoding(message.ContentType); // perf fix: changed buffer size passed to StreamReader int bufferSize; if (asyncCall || httpResponse == null) { bufferSize = 512; } else { int contentLength = (int)httpResponse.ContentLength; if (contentLength == -1) { bufferSize = 8000; } else if (contentLength <= 16000) { bufferSize = contentLength; } else { bufferSize = 16000; } } XmlTextReader reader; if (enc != null) { reader = new XmlTextReader(new StreamReader(message.Stream, enc, true, bufferSize)); } else { // CONSIDER: do i need to pass a buffer size somehow? reader = new XmlTextReader(message.Stream); } reader.Normalization = true; reader.XmlResolver = null; reader.MoveToContent(); // should be able to handle no ns, soap 1.1 ns, or soap 1.2 ns string encodingNs = EncodingNs; string envelopeNs = reader.NamespaceURI; if (envelopeNs == null || envelopeNs.Length == 0) { // ok to omit namespace -- assume correct version reader.ReadStartElement(Soap.Envelope); } else if (reader.NamespaceURI == Soap.Namespace) { reader.ReadStartElement(Soap.Envelope, Soap.Namespace); } else if (reader.NamespaceURI == Soap12.Namespace) { reader.ReadStartElement(Soap.Envelope, Soap12.Namespace); } else { throw new SoapException(Res.GetString(Res.WebInvalidEnvelopeNamespace, envelopeNs, EnvelopeNs), SoapException.VersionMismatchFaultCode); } reader.MoveToContent(); SoapHeaderHandling headerHandler = new SoapHeaderHandling(); headerHandler.ReadHeaders(reader, method.outHeaderSerializer, message.Headers, method.outHeaderMappings, SoapHeaderDirection.Out | SoapHeaderDirection.Fault, envelopeNs, method.use == SoapBindingUse.Encoded ? encodingNs : null); reader.MoveToContent(); reader.ReadStartElement(Soap.Body, envelopeNs); reader.MoveToContent(); if (reader.IsStartElement(Soap.Fault, envelopeNs)) { message.SetException(ReadSoapException(reader)); } else { if (method.oneWay) { reader.Skip(); message.SetParameterValues(new object[0]); } else { // SOAP12: not using encodingStyle //message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, method.use == SoapBindingUse.Encoded ? encodingNs : null)); message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader)); } } while (reader.NodeType == XmlNodeType.Whitespace) { reader.Skip(); } if (reader.NodeType == XmlNodeType.None) { reader.Skip(); } else { reader.ReadEndElement(); } while (reader.NodeType == XmlNodeType.Whitespace) { reader.Skip(); } if (reader.NodeType == XmlNodeType.None) { reader.Skip(); } else { reader.ReadEndElement(); } message.SetStage(SoapMessageStage.AfterDeserialize); message.RunExtensions(message.initializedExtensions); SoapHeaderHandling.SetHeaderMembers(message.Headers, this, method.outHeaderMappings, SoapHeaderDirection.Out | SoapHeaderDirection.Fault, true); if (message.Exception != null) { throw message.Exception; } return(message.GetParameterValues()); }