/// <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);
        }