/// <summary> /// Creates an instance of a WsRequestMessage class, parses the message into mtom body parts and assigns /// the start body part to the SoapMessage property. /// </summary> /// <param name="message">A byte array containing the message received by a transport.</param> /// <param name="boundary">A string containing a boundary element if the transport received an mtom message.</param> /// <param name="start"> /// A string containing the ID of the mtom body part that contains the soap envelope /// of the mtom attachment. /// </param> /// <remarks> /// Because Mtom message are identified via transport header fields (yuck). /// The transport services create this object and pass it to a message processor. If this is a normal soap request, no /// additional processing is required and the SoapMessage property is set to the request message. If this is an /// Mtom message, the transport header contains an mtom boundary element and start content id needed to parse /// the mtom message. The boundary element is used to identify the start and end of mtom body parts sections. /// The start content id is used to identify the specific mtom body part that contains a soap envelope that /// references the additional body part elements. If an mtom message is created the constructor parses the /// mtom message and creates an mtom body parts object. For mtom the constructor also sets the SoapMessage /// property to the body part identified by the startContentID parmeter. /// </remarks> /// <exception cref="ArgumentNullException">If the message parameter is null.</exception> public WsMessage(byte[] message, string boundary, string start) { Debug.Assert(message != null && boundary != null && start != null); // Create an mtom object and parse the transport request message. WsMtom mtom = new WsMtom(message); this.Message = mtom.ParseMessage(boundary); this.MessageType = WsMessageType.Mtom; this.BodyParts = mtom.BodyParts; System.Ext.Console.Write("Mtom message received. " + this.BodyParts.Count + " body parts found."); System.Ext.Console.Write("Soap Message:"); System.Ext.Console.Write(new String(System.Text.Encoding.UTF8.GetChars(this.BodyParts[0].Content.ToArray()))); }
/// <summary> /// Send an Http request containing an mtom message to an endpoint and waits for a response. /// </summary> /// <param name="bodyParts">A reference to the WsMtomBodyParts collection used to generate a mime multipart message.</param> /// <param name="endpointAddress">A string containing the endpoint address of a service that will receive /// <param name="isOneway">True = don't wait for response, false means wait for a response.</param> /// <param name="isChuncked">If true true the message will be chunk encoded.</param> /// <returns> /// A DpwSoapResponse object containing a WsWsaHeader and an XmlReader or null if no response is received /// or parsing fails. /// </returns> public DpwsSoapResponse SendRequest(ref WsMtomBodyParts bodyParts, string endpointAddress, bool isOneWay, bool isChuncked) { WsMtomParams mtomParams = new WsMtomParams(); if (bodyParts.Boundary == null) { bodyParts.Boundary = Guid.NewGuid().ToString() + '-' + Guid.NewGuid().ToString().Substring(0, 33); } mtomParams.start = bodyParts.Start; mtomParams.boundary = bodyParts.Boundary; WsMtom mtom = new WsMtom(); byte[] message = mtom.CreateMessage(bodyParts); WsMessage response = SendRequest(message, endpointAddress, isOneWay, isChuncked, mtomParams); if (isOneWay) { return(null); } XmlReader reader; WsWsaHeader header; try { reader = WsSoapMessageParser.ParseSoapMessage(response.Message, out header); bodyParts = response.BodyParts; } catch { System.Ext.Console.Write("ParseSoapMessage failed."); return(null); } return(new DpwsSoapResponse(header, reader)); }
/// <summary> /// Processes a message /// </summary> /// <param name="stream">The message being processed.</param> /// <param name="ctx">The context associated with the message.</param> /// <returns>The handling status for this operation.</returns> protected override ChainResult OnProcessInputMessage(ref WsMessage msg, BindingContext ctx) { if (msg == null) { return(ChainResult.Abort); } ArrayList props = ctx.BindingProperties; if (props != null) { int len = props.Count; for (int j = 0; j < len; j++) { BindingProperty prop = (BindingProperty)props[j]; if (prop.Name == HttpKnownHeaderNames.ContentType) { string strContentType = ((string)prop.Value).ToLower(); if (strContentType.IndexOf("multipart/related;") == 0) { // Create the mtom header class msg.MtomPropeties = new WsMtomParams(); // Parse Mtom Content-Type parameters string[] fields = strContentType.Substring(18).Split(';'); int fieldsLen = fields.Length; for (int i = 0; i < fieldsLen; ++i) { string type = fields[i]; int idx = type.IndexOf('='); if (idx != -1) { string param = type.Substring(0, idx).Trim(); string value = type.Substring(idx + 1).Trim('\"'); switch (param.ToUpper()) { case "BOUNDARY": if (param.Length > 72) { throw new ArgumentException("Mime boundary element length exceeded.", "boundary"); } msg.MtomPropeties.boundary = value; break; case "TYPE": msg.MtomPropeties.type = value; break; case "START": msg.MtomPropeties.start = value; break; case "START-INFO": msg.MtomPropeties.startInfo = value; break; default: break; } } } // Check required Mtom fields if (msg.MtomPropeties.boundary == null || msg.MtomPropeties.type == null || msg.MtomPropeties.start == null) { throw new WsFaultException(msg.Header, WsFaultType.WseInvalidMessage); } WsMtom mtom = new WsMtom((byte[])msg.Body); msg.Body = mtom.ParseMessage(msg.MtomPropeties.boundary); msg.BodyParts = mtom.BodyParts; } else if (strContentType.IndexOf("application/soap+xml") != 0) { throw new WsFaultException(msg.Header, WsFaultType.WseInvalidMessage); } } } } if (msg.Body == null) { return(ChainResult.Continue); } MemoryStream requestStream = new MemoryStream((byte[])msg.Body); XmlReader reader = XmlReader.Create(requestStream); WsWsaHeader hdr = new WsWsaHeader(); reader.ReadStartElement("Envelope", WsWellKnownUri.SoapNamespaceUri); reader.MoveToContent(); if (ctx.Version.IncludeSoapHeaders || reader.LocalName == "Header") { hdr.ParseHeader(reader, ctx.Version); } msg.Header = hdr; reader.ReadStartElement("Body", WsWellKnownUri.SoapNamespaceUri); if (msg.Deserializer != null) { msg.Body = ((DataContractSerializer)msg.Deserializer).ReadObject(reader); reader.Dispose(); } else { msg.Reader = reader; } return(ChainResult.Continue); }
/// <summary> /// Processes a message /// </summary> /// <param name="msg">The message being processed.</param> /// <param name="ctx">The context associated with the message.</param> /// <returns>The handling status for this operation.</returns> protected override ChainResult OnProcessOutputMessage(ref WsMessage msg, BindingContext ctx) { byte[] data = null; // if the body is a byte[] then it is already serialized (UDP stuff) if (msg == null || (msg.Body != null && msg.Body is byte[])) { return(ChainResult.Continue); } // Build response message using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create()) { WsSoapMessageWriter smw = new WsSoapMessageWriter(ctx.Version); // Write start message up to body element content smw.WriteSoapMessageStart(xmlWriter, msg, ctx.Version.IncludeSoapHeaders); if (msg.Body != null && msg.Serializer != null) { DataContractSerializer ser = (DataContractSerializer)msg.Serializer; // Serialize the body element ser.WriteObject(xmlWriter, msg.Body); if (ser.BodyParts != null && ser.BodyParts.Count > 0) { msg.BodyParts = ser.BodyParts; } } // Write end message smw.WriteSoapMessageEnd(xmlWriter); data = xmlWriter.ToArray(); } WsMtomBodyParts bodyParts = msg.BodyParts; if (bodyParts != null) { DataContractSerializer reqDcs = (DataContractSerializer)msg.Serializer; bodyParts.Start = "<soap@soap>"; bodyParts.AddStart(reqDcs.CreateNewBodyPart(data, bodyParts.Start)); if (reqDcs.BodyParts.Count > 0) { bodyParts.Add(reqDcs.BodyParts[0]); } WsMtomParams mtomParams = new WsMtomParams(); if (bodyParts.Boundary == null) { bodyParts.Boundary = Guid.NewGuid().ToString() + '-' + Guid.NewGuid().ToString().Substring(0, 33); } mtomParams.start = bodyParts.Start; mtomParams.boundary = bodyParts.Boundary; msg.MtomPropeties = mtomParams; WsMtom mtom = new WsMtom(); data = mtom.CreateMessage(bodyParts); } msg.Body = data; return(ChainResult.Continue); }