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()); }
object[] ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, bool asyncCall) { SoapClientMethod method = message.Method; // 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, false); 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 bool isSoap = ContentType.IsSoap(message.ContentType); if (!isSoap || (isSoap && (httpResponse != null) && (httpResponse.ContentLength == 0))) { // 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) + Environment.NewLine + RequestResponseUtils.CreateResponseExceptionString(response, responseStream)); } if (message.Exception != null) { throw message.Exception; } // perf fix: changed buffer size passed to StreamReader int bufferSize; if (asyncCall || httpResponse == null) bufferSize = 512; else { bufferSize = RequestResponseUtils.GetBufferSize((int)httpResponse.ContentLength); } XmlReader reader = GetReaderForMessage(message, bufferSize); if (reader == null) throw new InvalidOperationException(Res.GetString(Res.WebNullReaderForMessage)); reader.MoveToContent(); int depth = reader.Depth; // 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.Element.Envelope); else if (reader.NamespaceURI == Soap.Namespace) reader.ReadStartElement(Soap.Element.Envelope, Soap.Namespace); else if (reader.NamespaceURI == Soap12.Namespace) reader.ReadStartElement(Soap.Element.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, false); reader.MoveToContent(); reader.ReadStartElement(Soap.Element.Body, envelopeNs); reader.MoveToContent(); if (reader.IsStartElement(Soap.Element.Fault, envelopeNs)) { message.Exception = ReadSoapException(reader); } else { if (method.oneWay) { reader.Skip(); message.SetParameterValues(new object[0]); } else { TraceMethod caller = Tracing.On ? new TraceMethod(this, "ReadResponse") : null; bool isEncodedSoap = method.use == SoapBindingUse.Encoded; if (Tracing.On) Tracing.Enter(Tracing.TraceId(Res.TraceReadResponse), caller, new TraceMethod(method.returnSerializer, "Deserialize", reader, isEncodedSoap ? encodingNs : null)); bool useDeserializationEvents = !isEncodedSoap && (WebServicesSection.Current.SoapEnvelopeProcessing.IsStrict || Tracing.On); if (useDeserializationEvents) { XmlDeserializationEvents events = Tracing.On ? Tracing.GetDeserializationEvents() : RuntimeUtils.GetDeserializationEvents(); message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, null, events)); } else { message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, isEncodedSoap ? encodingNs : null)); } if (Tracing.On) Tracing.Exit(Tracing.TraceId(Res.TraceReadResponse), caller); } } // Consume soap:Body and soap:Envelope closing tags while (depth < reader.Depth && reader.Read()) { // Nothing, just read on } // consume end tag if (reader.NodeType == XmlNodeType.EndElement) { reader.Read(); } message.SetStage(SoapMessageStage.AfterDeserialize); message.RunExtensions(message.initializedExtensions, false); SoapHeaderHandling.SetHeaderMembers(message.Headers, this, method.outHeaderMappings, SoapHeaderDirection.Out | SoapHeaderDirection.Fault, true); if (message.Exception != null) throw message.Exception; return message.GetParameterValues(); }
object[] ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, bool asyncCall) { SoapClientMethod method = message.Method; // 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, false); 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 bool isSoap = ContentType.IsSoap(message.ContentType); if (!isSoap || (isSoap && (httpResponse != null) && (httpResponse.ContentLength == 0))) { // 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) + Environment.NewLine + RequestResponseUtils.CreateResponseExceptionString(response, responseStream)); } } if (message.Exception != null) { throw message.Exception; } // perf fix: changed buffer size passed to StreamReader int bufferSize; if (asyncCall || httpResponse == null) { bufferSize = 512; } else { bufferSize = RequestResponseUtils.GetBufferSize((int)httpResponse.ContentLength); } XmlReader reader = GetReaderForMessage(message, bufferSize); if (reader == null) { throw new InvalidOperationException(Res.GetString(Res.WebNullReaderForMessage)); } reader.MoveToContent(); int depth = reader.Depth; // 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.Element.Envelope); } else if (reader.NamespaceURI == Soap.Namespace) { reader.ReadStartElement(Soap.Element.Envelope, Soap.Namespace); } else if (reader.NamespaceURI == Soap12.Namespace) { reader.ReadStartElement(Soap.Element.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, false); reader.MoveToContent(); reader.ReadStartElement(Soap.Element.Body, envelopeNs); reader.MoveToContent(); if (reader.IsStartElement(Soap.Element.Fault, envelopeNs)) { message.Exception = ReadSoapException(reader); } else { if (method.oneWay) { reader.Skip(); message.SetParameterValues(new object[0]); } else { TraceMethod caller = Tracing.On ? new TraceMethod(this, "ReadResponse") : null; bool isEncodedSoap = method.use == SoapBindingUse.Encoded; if (Tracing.On) { Tracing.Enter(Tracing.TraceId(Res.TraceReadResponse), caller, new TraceMethod(method.returnSerializer, "Deserialize", reader, isEncodedSoap ? encodingNs : null)); } bool useDeserializationEvents = !isEncodedSoap && (WebServicesSection.Current.SoapEnvelopeProcessing.IsStrict || Tracing.On); if (useDeserializationEvents) { XmlDeserializationEvents events = Tracing.On ? Tracing.GetDeserializationEvents() : RuntimeUtils.GetDeserializationEvents(); message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, null, events)); } else { message.SetParameterValues((object[])method.returnSerializer.Deserialize(reader, isEncodedSoap ? encodingNs : null)); } if (Tracing.On) { Tracing.Exit(Tracing.TraceId(Res.TraceReadResponse), caller); } } } // Consume soap:Body and soap:Envelope closing tags while (depth < reader.Depth && reader.Read()) { // Nothing, just read on } // consume end tag if (reader.NodeType == XmlNodeType.EndElement) { reader.Read(); } message.SetStage(SoapMessageStage.AfterDeserialize); message.RunExtensions(message.initializedExtensions, false); SoapHeaderHandling.SetHeaderMembers(message.Headers, this, method.outHeaderMappings, SoapHeaderDirection.Out | SoapHeaderDirection.Fault, true); if (message.Exception != null) { throw message.Exception; } return(message.GetParameterValues()); }