/// <summary> /// Parses the message XML. /// </summary> /// <param name="reader">The reader.</param> private void ParseMessageXml(EwsXmlReader reader) { // E12 and E14 return the MessageXml element in different // namespaces (types namespace for E12, errors namespace in E14). To // avoid this problem, the parser will match the namespace from the // start and end elements. XmlNamespace elementNS = EwsUtilities.GetNamespaceFromUri(reader.NamespaceUri); if (!reader.IsEmptyElement) { do { reader.Read(); if (reader.IsStartElement() && !reader.IsEmptyElement) { switch (reader.LocalName) { case XmlElementNames.Value: this.errorDetails.Add( reader.ReadAttributeValue(XmlAttributeNames.Name), reader.ReadElementValue()); break; default: break; } } }while (!reader.IsEndElement(elementNS, XmlElementNames.MessageXml)); } }
/// <summary> /// Parses the soap:Fault content. /// </summary> /// <param name="reader">The reader.</param> /// <param name="soapNamespace">The SOAP namespace to use.</param> /// <returns>SOAP fault details.</returns> internal static SoapFaultDetails Parse(EwsXmlReader reader, XmlNamespace soapNamespace) { SoapFaultDetails soapFaultDetails = new SoapFaultDetails(); do { reader.Read(); if (reader.NodeType == XmlNodeType.Element) { switch (reader.LocalName) { case XmlElementNames.SOAPFaultCodeElementName: soapFaultDetails.FaultCode = reader.ReadElementValue(); break; case XmlElementNames.SOAPFaultStringElementName: soapFaultDetails.FaultString = reader.ReadElementValue(); break; case XmlElementNames.SOAPFaultActorElementName: soapFaultDetails.FaultActor = reader.ReadElementValue(); break; case XmlElementNames.SOAPDetailElementName: soapFaultDetails.ParseDetailNode(reader); break; default: break; } } }while (!reader.IsEndElement(soapNamespace, XmlElementNames.SOAPFaultElementName)); return(soapFaultDetails); }
/// <summary> /// Function that parses the RSTR from Windows Live and pulls out all the important pieces /// of data from it. /// </summary> /// <param name="rstResponse">The RSTR, positioned at the beginning of the SOAP body.</param> private void ParseWindowsLiveRSTResponseBody(EwsXmlReader rstResponse) { // Read the WS-Trust RequestSecurityTokenResponseCollection node. rstResponse.ReadStartElement( XmlNamespace.WSTrustFebruary2005, RequestSecurityTokenResponseCollectionElementName); // Skip the first token - our interest is in the second token (the service token). rstResponse.SkipElement( XmlNamespace.WSTrustFebruary2005, RequestSecurityTokenResponseElementName); // Now process the second token. rstResponse.ReadStartElement( XmlNamespace.WSTrustFebruary2005, RequestSecurityTokenResponseElementName); while (!rstResponse.IsEndElement( XmlNamespace.WSTrustFebruary2005, RequestSecurityTokenResponseElementName)) { // Watch for the EncryptedData element - when we find it, parse out the appropriate bits of data. // // Also watch for the "pp" element in the Passport SOAP fault namespace, which indicates that // something went wrong with the token request. If we find it, trace and throw accordingly. if (rstResponse.IsStartElement() && (rstResponse.LocalName == EncryptedDataElementName) && (rstResponse.NamespaceUri == XmlEncNamespace)) { this.SecurityToken = rstResponse.ReadOuterXml(); } else if (rstResponse.IsStartElement(XmlNamespace.PassportSoapFault, PpElementName)) { if (this.TraceEnabled) { string logMessage = string.Format( "Windows Live reported an error retrieving the token - {0}", rstResponse.ReadOuterXml()); this.traceListener.Trace("WindowsLiveResponse", logMessage); } throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, EncryptedDataElementName)); } // Move to the next bit of data... rstResponse.Read(); } // If we didn't find the token, throw. if (this.SecurityToken == null) { if (this.TraceEnabled) { string logMessage = string.Format( "Did not find all required parts of the Windows Live response - " + "Security Token - {0}", (this.SecurityToken == null) ? "NOT FOUND" : "found"); this.traceListener.Trace("WindowsLiveResponse", logMessage); } throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, "No security token found.")); } // Read past the RequestSecurityTokenResponseCollection end element. rstResponse.Read(); }
/// <summary> /// Function that parses the SOAP headers from the response to the RST to Windows Live. /// </summary> /// <param name="rstResponse">The Windows Live response, positioned at the beginning of the SOAP headers.</param> private void ReadWindowsLiveRSTResponseHeaders(EwsXmlReader rstResponse) { // Read the beginning of the SOAP header, then go looking for the Passport SOAP fault section... rstResponse.ReadStartElement( WindowsLiveSoapNamespacePrefix, XmlElementNames.SOAPHeaderElementName); // Attempt to read to the psf:pp element - if at the end of the ReadToDescendant call we're at the // end element for the SOAP headers, we didn't find it. rstResponse.ReadToDescendant(XmlNamespace.PassportSoapFault, PpElementName); if (rstResponse.IsEndElement(WindowsLiveSoapNamespacePrefix, XmlElementNames.SOAPHeaderElementName)) { // We didn't find the psf:pp element - without that, we don't know what happened - // something went wrong. Trace and throw. if (this.TraceEnabled) { this.traceListener.Trace( "WindowsLiveResponse", "Could not find Passport SOAP fault information in Windows Live response"); } throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, PpElementName)); } // Now that we've found the psf:pp element, look for the 'reqstatus' element under it. If after // the ReadToDescendant call we're at the end element for the psf:pp element, we didn't find it. rstResponse.ReadToDescendant(XmlNamespace.PassportSoapFault, ReqstatusElementName); if (rstResponse.IsEndElement(XmlNamespace.PassportSoapFault, PpElementName)) { // We didn't find the "reqstatus" element - without that, we don't know what happened - // something went wrong. Trace and throw. if (this.TraceEnabled) { this.traceListener.Trace( "WindowsLiveResponse", "Could not find reqstatus element in Passport SOAP fault information in Windows Live response"); } throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, ReqstatusElementName)); } // Now that we've found the reqstatus element, get its value. string reqstatus = rstResponse.ReadElementValue(); // Read to body tag in both success and failure cases, // since we need to trace the fault response in failure cases while (!rstResponse.IsEndElement(WindowsLiveSoapNamespacePrefix, XmlElementNames.SOAPHeaderElementName)) { rstResponse.Read(); } if (!string.Equals(reqstatus, SuccessfulReqstatus)) { // Our request status was non-zero - something went wrong. Trace and throw. if (this.TraceEnabled) { string logMessage = string.Format( "Received status {0} from Windows Live instead of {1}.", reqstatus, SuccessfulReqstatus); this.traceListener.Trace("WindowsLiveResponse", logMessage); rstResponse.ReadStartElement( WindowsLiveSoapNamespacePrefix, XmlElementNames.SOAPBodyElementName); // Trace Fault Information this.traceListener.Trace( "WindowsLiveResponse", string.Format( "Windows Live reported Fault : {0}", rstResponse.ReadInnerXml())); } throw new ServiceRequestException(string.Format(Strings.ServiceRequestFailed, ReqstatusElementName + ": " + reqstatus)); } }
/// <summary> /// Parses the detail node. /// </summary> /// <param name="reader">The reader.</param> private void ParseDetailNode(EwsXmlReader reader) { do { reader.Read(); if (reader.NodeType == XmlNodeType.Element) { switch (reader.LocalName) { case XmlElementNames.EwsResponseCodeElementName: try { this.ResponseCode = reader.ReadElementValue <ServiceError>(); } catch (ArgumentException) { // ServiceError couldn't be mapped to enum value, treat as an ISE this.ResponseCode = ServiceError.ErrorInternalServerError; } break; case XmlElementNames.EwsMessageElementName: this.Message = reader.ReadElementValue(); break; case XmlElementNames.EwsLineElementName: this.LineNumber = reader.ReadElementValue <int>(); break; case XmlElementNames.EwsPositionElementName: this.PositionWithinLine = reader.ReadElementValue <int>(); break; case XmlElementNames.EwsErrorCodeElementName: try { this.ErrorCode = reader.ReadElementValue <ServiceError>(); } catch (ArgumentException) { // ServiceError couldn't be mapped to enum value, treat as an ISE this.ErrorCode = ServiceError.ErrorInternalServerError; } break; case XmlElementNames.EwsExceptionTypeElementName: this.ExceptionType = reader.ReadElementValue(); break; case XmlElementNames.MessageXml: this.ParseMessageXml(reader); break; default: // Ignore any other details break; } } }while (!reader.IsEndElement(XmlNamespace.NotSpecified, XmlElementNames.SOAPDetailElementName)); }