/// <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) { ArrayList props = ctx.BindingProperties; byte[] message = null; string contentType = "text/plain"; if (msg != null) { message = msg.Body as byte[]; if (msg.BodyParts != null) { contentType = "Multipart/Related;boundary=" + msg.MtomPropeties.boundary + ";type=\"application/xop+xml\";start=\"" + msg.MtomPropeties.start + "\";start-info=\"application/soap+xml\""; ctx.BindingProperties.Add(new BindingProperty("header", HttpKnownHeaderNames.Server, "Microsoft-MF HTTP 1.0")); ctx.BindingProperties.Add(new BindingProperty("header", HttpKnownHeaderNames.MimeVersion, "1.0")); ctx.BindingProperties.Add(new BindingProperty("header", HttpKnownHeaderNames.Date, DateTime.Now.ToString())); } else { contentType = "application/soap+xml; charset=utf-8"; } } if (ctx is ClientBindingContext) { if (message == null) { return(ChainResult.Abort); } HttpWebRequest request; try { if (!m_persistConn || ctx.ContextObject == null) { request = HttpWebRequest.Create(new Uri(m_transportUri.AbsoluteUri)) as HttpWebRequest; request.Timeout = (int)(ctx.OpenTimeout.Ticks / TimeSpan.TicksPerMillisecond); request.ReadWriteTimeout = (int)(ctx.ReceiveTimeout.Ticks / TimeSpan.TicksPerMillisecond); ctx.ContextObject = request; } else { request = (HttpWebRequest)ctx.ContextObject; request.Reset(); } // Post method request.Method = "POST"; WebHeaderCollection headers = request.Headers; request.ContentType = contentType; request.UserAgent = "MFWsAPI"; request.Headers.Add(HttpKnownHeaderNames.CacheControl, "no-cache"); request.Headers.Add(HttpKnownHeaderNames.Pragma, "no-cache"); if (props != null) { int len = props.Count; for (int i = 0; i < len; i++) { BindingProperty prop = (BindingProperty)props[i]; string container = prop.Container; if (container == "header") { headers.Add(prop.Name, (string)prop.Value); } else if (container == null || container == "") { string name = prop.Name; if (name == HttpKnownHeaderNames.ContentType) { request.ContentType = (string)prop.Value; } else if (name == HttpKnownHeaderNames.UserAgent) { request.UserAgent = (string)prop.Value; } } } } if (message != null) { System.Ext.Console.Write("Http message sent: "); System.Ext.Console.Write(message); request.ContentLength = message.Length; using (Stream stream = request.GetRequestStream()) { // Write soap message stream.Write(message, 0, message.Length); // Flush the stream and force a write stream.Flush(); } } } catch { ctx.ContextObject = null; throw; } } else { HttpListenerContext listenerContext = ctx.ContextObject as HttpListenerContext; if (listenerContext == null) { return(ChainResult.Abort); } HttpListenerResponse listenerResponse = listenerContext.Response; if (listenerResponse == null || listenerResponse.OutputStream == null) { ctx.ContextObject = null; return(ChainResult.Abort); } try { StreamWriter streamWriter = new StreamWriter(listenerResponse.OutputStream); // Write Header, if message is null write accepted if (message == null || (msg != null && msg.Header != null && msg.Header.IsFaultMessage)) { listenerResponse.StatusCode = 202; } else { listenerResponse.StatusCode = 200; } // Check to see it the hosted service is sending mtom WebHeaderCollection headers = listenerResponse.Headers; listenerResponse.ContentType = contentType; bool isChunked = false; if (props != null) { int len = props.Count; for (int i = 0; i < len; i++) { BindingProperty prop = (BindingProperty)props[i]; string container = prop.Container; string name = prop.Name; string value = (string)prop.Value; if (container == "header") { if (!isChunked && name == HttpKnownHeaderNames.TransferEncoding && value.ToLower() == "chunked") { isChunked = true; } headers.Add(name, (string)prop.Value); } else if (container == null || container == "") { if (name == HttpKnownHeaderNames.ContentType) { listenerResponse.ContentType = (string)prop.Value; System.Ext.Console.Write(HttpKnownHeaderNames.ContentType + ": " + listenerResponse.ContentType); } } } } // If chunked encoding is enabled write chunked message else write Content-Length if (isChunked) { // Chunk message int bufferIndex = 0; int chunkSize = 0; int defaultChunkSize = 0xff; #if DEBUG byte[] displayBuffer = new byte[defaultChunkSize]; #endif while (bufferIndex < message.Length) { // Calculate chunk size and write to stream chunkSize = message.Length - bufferIndex < defaultChunkSize ? message.Length - bufferIndex : defaultChunkSize; streamWriter.WriteLine(chunkSize.ToString("{0:X}")); System.Ext.Console.Write(chunkSize.ToString("{0:X}")); // Write chunk streamWriter.WriteBytes(message, bufferIndex, chunkSize); streamWriter.WriteLine(); #if DEBUG Array.Copy(message, bufferIndex, displayBuffer, 0, chunkSize); System.Ext.Console.Write(displayBuffer, bufferIndex, chunkSize); #endif // Adjust buffer index bufferIndex = bufferIndex + chunkSize; } // Write 0 length and blank line streamWriter.WriteLine("0"); streamWriter.WriteLine(); System.Ext.Console.Write("0"); System.Ext.Console.Write(""); } else { if (message == null) { listenerResponse.ContentLength64 = 0; } else { listenerResponse.ContentLength64 = message.Length; } System.Ext.Console.Write("Content Length: " + listenerResponse.ContentLength64); // If an empty message is returned (i.e. oneway request response) don't send if (message != null && message.Length > 0) { System.Ext.Console.Write(message); // Write soap message streamWriter.WriteBytes(message, 0, message.Length); } } // Flush the stream and return streamWriter.Flush(); } catch { return(ChainResult.Abort); } finally { if (m_persistConn) { listenerResponse.Detach(); } else { listenerContext.Close(ctx.CloseTimeout.Seconds); ctx.ContextObject = null; } } } return(ChainResult.Handled); }