public WsMessage GetResponse(WsMessage req)
        {
            XmlReader   reader = req.Reader;
            WsWsaHeader header = req.Header;

            // Build ProbeMatch
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                // Write service type namespaces
                WsXmlNamespaces additionalPrefixes = new WsXmlNamespaces();
                if (Device.Host != null)
                {
                    additionalPrefixes = new WsXmlNamespaces();
                    additionalPrefixes.Add(Device.Host.ServiceNamespace);
                }

                WsServiceEndpoints hostedServices = Device.HostedServices;
                int count = hostedServices.Count;
                for (int i = 0; i < count; i++)
                {
                    DpwsHostedService hostedService = (DpwsHostedService)hostedServices[i];

                    // Don't return Mex Service namespace
                    if (hostedService.ServiceTypeName == "Internal")
                    {
                        continue;
                    }

                    additionalPrefixes.Add(hostedService.ServiceNamespace);
                }

                WsWsaHeader responseHeader = new WsWsaHeader(
                    WsWellKnownUri.WstNamespaceUri + "/GetResponse",                        // Action
                    header.MessageID,                                                       // RelatesTo
                    header.ReplyTo.Address.AbsoluteUri,                                     // To
                    null, null, null);

                WsMessage resp = new WsMessage(responseHeader, null, WsPrefix.Wsx | WsPrefix.Wsdp, additionalPrefixes,
                                               new WsAppSequence(Device.AppSequence, Device.SequenceID, Device.MessageID));

                WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version);
                smw.WriteSoapMessageStart(xmlWriter, resp);

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsx, "Metadata", null);

                // Write ThisModel metadata section
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsx, "MetadataSection", null);
                xmlWriter.WriteAttributeString("Dialect", m_version.WsdpNamespaceUri + "/ThisModel");

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ThisModel", null);
                if (Device.ThisModel.Manufacturer != null && Device.ThisModel.Manufacturer != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "Manufacturer", null);
                    xmlWriter.WriteString(Device.ThisModel.Manufacturer);
                    xmlWriter.WriteEndElement(); // End Manufacturer
                }

                if (Device.ThisModel.ManufacturerUrl != null && Device.ThisModel.ManufacturerUrl != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ManufacturerUrl", null);
                    xmlWriter.WriteString(Device.ThisModel.ManufacturerUrl);
                    xmlWriter.WriteEndElement(); // End ManufacturerUrl
                }

                if (Device.ThisModel.ModelName != null && Device.ThisModel.ModelName != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ModelName", null);
                    xmlWriter.WriteString(Device.ThisModel.ModelName);
                    xmlWriter.WriteEndElement(); // End ModelName
                }

                if (Device.ThisModel.ModelNumber != null && Device.ThisModel.ModelNumber != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ModelNumber", null);
                    xmlWriter.WriteString(Device.ThisModel.ModelNumber);
                    xmlWriter.WriteEndElement(); // End ModelNumber
                }

                if (Device.ThisModel.ModelUrl != null && Device.ThisModel.ModelUrl != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ModelUrl", null);
                    xmlWriter.WriteString(Device.ThisModel.ModelUrl);
                    xmlWriter.WriteEndElement(); // End ModelUrl
                }

                if (Device.ThisModel.PresentationUrl != null && Device.ThisModel.PresentationUrl != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "PresentationUrl", null);
                    xmlWriter.WriteString(Device.ThisModel.PresentationUrl);
                    xmlWriter.WriteEndElement(); // End PresentationUrl
                }

                if (Device.ThisModel.Any != null)
                {
                    Device.ThisModel.Any.WriteTo(xmlWriter);
                }

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ModelName", null);
                xmlWriter.WriteString(Device.ThisModel.ModelName);
                xmlWriter.WriteEndElement(); // End ModelName

                xmlWriter.WriteEndElement(); // End ThisModel
                xmlWriter.WriteEndElement(); // End MetadataSection

                // Write ThisDevice metadata section
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsx, "MetadataSection", null);
                xmlWriter.WriteAttributeString("Dialect", m_version.WsdpNamespaceUri + "/ThisDevice");

                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ThisDevice", null);
                if (Device.ThisDevice.FriendlyName != null && Device.ThisDevice.FriendlyName != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "FriendlyName", null);
                    xmlWriter.WriteString(Device.ThisDevice.FriendlyName);
                    xmlWriter.WriteEndElement(); // End FriendlyName
                }

                if (Device.ThisDevice.FirmwareVersion != null && Device.ThisDevice.FirmwareVersion != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "FirmwareVersion", null);
                    xmlWriter.WriteString(Device.ThisDevice.FirmwareVersion);
                    xmlWriter.WriteEndElement(); // End FirmwareVersion
                }

                if (Device.ThisDevice.SerialNumber != null && Device.ThisDevice.SerialNumber != "")
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "SerialNumber", null);
                    xmlWriter.WriteString(Device.ThisDevice.SerialNumber);
                    xmlWriter.WriteEndElement(); // End SerialNumber
                }

                if (Device.ThisDevice.Any != null)
                {
                    Device.ThisDevice.Any.WriteTo(xmlWriter);
                }

                xmlWriter.WriteEndElement(); // End ThisDevice
                xmlWriter.WriteEndElement(); // End MetadataSection

                // Write next MetadataSection
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsx, "MetadataSection", null);
                xmlWriter.WriteAttributeString("Dialect", m_version.WsdpNamespaceUri + "/Relationship");

                // Write Relationship Elements
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "Relationship", null);
                xmlWriter.WriteAttributeString("Type", m_version.WsdpNamespaceUri + "/host");

                // List used to maintain service endpoints that have been processed. Because the DPWS spec allows
                // for multiple service types at a single endpoint address, we must make sure we only create
                // a relationship once for all of the types at a service endpoint.
                ArrayList processedEndpointList = new ArrayList();

                // If a Host type exist add it
                if (Device.Host != null)
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "Host", null);
                    WsWsaEndpointRef endpointReference;
                    endpointReference = (WsWsaEndpointRef)Device.Host.EndpointRefs[0];
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "EndpointReference", null);
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                    xmlWriter.WriteString(endpointReference.Address.AbsoluteUri);
                    xmlWriter.WriteEndElement(); // End Address
                    xmlWriter.WriteEndElement(); // End EndpointReference

                    // Build list of all service types that share this endpoint address

                    /*
                     * string serviceTypes = null;
                     * if ((serviceTypes = BuildServiceTypesList(Device.Host, processedEndpointList)) == null)
                     *  serviceTypes = Device.Host.ServiceNamespace.Prefix + ":" + Device.Host.ServiceTypeName;
                     * else
                     *  serviceTypes = serviceTypes + " " + Device.Host.ServiceNamespace.Prefix + ":" + Device.Host.ServiceTypeName;
                     */

                    // Write service types
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "Types", null);
                    xmlWriter.WriteString(Device.Host.ServiceNamespace.Prefix + ":" + Device.Host.ServiceTypeName);
                    xmlWriter.WriteEndElement(); // End Types

                    // Write Service ID
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ServiceId", null);
                    xmlWriter.WriteString(Device.Host.ServiceID);
                    xmlWriter.WriteEndElement(); // End ServiceID

                    xmlWriter.WriteEndElement(); // End Hosted

                    // Update processed endpoint list
                    processedEndpointList.Add(Device.Host.EndpointAddress);
                }

                // Add hosted services types
                int serviceCount = hostedServices.Count;
                DpwsHostedService currentService;
                for (int i = 0; i < serviceCount; i++)
                {
                    currentService = (DpwsHostedService)hostedServices[i];

                    // Don't return Mex Service type
                    if (currentService.ServiceTypeName == "Internal")
                    {
                        continue;
                    }

                    // Build list of all service types that share this endpoint address
                    string serviceTypes = null;
                    if ((serviceTypes = BuildServiceTypesList(currentService, processedEndpointList)) == null)
                    {
                        continue;
                    }

                    // Write hosted start element
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "Hosted", null);

                    // Write n number of endpoint references
                    int epRefCount = currentService.EndpointRefs.Count;
                    for (int j = 0; j < epRefCount; j++)
                    {
                        xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "EndpointReference", null);
                        xmlWriter.WriteStartElement(WsNamespacePrefix.Wsa, "Address", null);
                        xmlWriter.WriteString(currentService.EndpointRefs[j].Address.AbsoluteUri);
                        xmlWriter.WriteEndElement(); // End Address
                        xmlWriter.WriteEndElement(); // End EndpointReference
                    }

                    // Write service types
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "Types", null);
                    xmlWriter.WriteString(currentService.ServiceNamespace.Prefix + ":" + currentService.ServiceTypeName);
                    xmlWriter.WriteEndElement(); // End Types

                    // Write Service ID
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wsdp, "ServiceId", null);
                    xmlWriter.WriteString(currentService.ServiceID);
                    xmlWriter.WriteEndElement(); // End ServiceID

                    xmlWriter.WriteEndElement(); // End Hosted

                    // Update processed endpoint list
                    processedEndpointList.Add(currentService.EndpointAddress);
                }

                xmlWriter.WriteEndElement(); // End Relastionship
                xmlWriter.WriteEndElement(); // End MetadataSection

                xmlWriter.WriteEndElement(); // End Metadata

                smw.WriteSoapMessageEnd(xmlWriter);

                resp.Body = xmlWriter.ToArray();

                return(resp);
            }
        }
        /// <summary>
        /// Use to subscribe to a devices, hosted service event sources.
        /// </summary>
        /// <param name="subscriptionRequest">
        /// A DpwsSubscriptionRequest object containing the address of the service hosting the desired event,
        /// the address where the event is sent, an optional address where subscription end messages are sent,
        /// A subscription expiration (in duration format) and an optional user defined identifier.
        /// </param>
        /// <returns>
        /// A DpwsEventSubscription containing the the subscription managers address, the time when the subscription
        /// expires (duration) and optional reference parameters and properties. Per spec the
        /// sub mananger may assign a different duration value than that specified in the request.
        /// </returns>
        /// <exception cref="ArgumentNullException">If required subscription parameters are not set.</exception>
        public DpwsEventSubscription Subscribe(DpwsSubscribeRequest subscriptionRequest)
        {
            if ((subscriptionRequest.SubscriptionType == null) ||
                (subscriptionRequest.SubscriptionType.TypeName == null) ||
                (subscriptionRequest.SubscriptionType.NamespaceUri == null) ||
                (subscriptionRequest.EndpointAddress == null) ||
                (subscriptionRequest.NotifyTo == null) ||
                (subscriptionRequest.NotifyTo.Address == null))
            {
                throw new ArgumentNullException();
            }

            // Convert the address string to a Uri
            Uri serviceUri = null;

            try
            {
                serviceUri = subscriptionRequest.EndpointAddress;
                if (serviceUri.Scheme != "http")
                {
                    System.Ext.Console.Write("");
                    System.Ext.Console.Write("Invalid endpoint address. Must be a Uri. Http Uri schemes only.");
                    System.Ext.Console.Write("");
                    return(null);
                }
            }
            catch (Exception e)
            {
                System.Ext.Console.Write("");
                System.Ext.Console.Write(e.Message);
                System.Ext.Console.Write("");
                return(null);
            }

            // Performance debugging
            DebugTiming timeDebuger       = new DebugTiming();
            long        startTime         = timeDebuger.ResetStartTime("");
            WsMessage   subscribeResponse = null;

            // Build Subscribe Request
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                WsWsaHeader header = new WsWsaHeader(
                    m_version.EventingNamespace + "/Subscribe",     // Action
                    null,                                           // RelatesTo
                    serviceUri.AbsoluteUri,                         // To
                    m_version.AnonymousUri,                         // ReplyTo
                    null, null);                                    // From, Any

                WsXmlNamespaces additionalPrefixes = new WsXmlNamespaces();
                additionalPrefixes.Add(new WsXmlNamespace("myPrefix", subscriptionRequest.SubscriptionType.NamespaceUri));

                WsMessage msg = new WsMessage(header, null, WsPrefix.Wsd | WsPrefix.Wse, additionalPrefixes, null);

                WsSoapMessageWriter smw = new WsSoapMessageWriter(m_version);
                String messageID        = smw.WriteSoapMessageStart(xmlWriter, msg);

                // Performance debuging
                timeDebuger.PrintElapsedTime("*****Write Header Took");

                // write body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Subscribe", null);

                // If EndTo is set write it
                if (subscriptionRequest.EndTo != null)
                {
                    WriteEndpointRef(xmlWriter, subscriptionRequest.EndTo, "EndTo");
                }

                // Add the delivery element and NotifyTo endpoint
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Delivery", null);
                xmlWriter.WriteAttributeString("Mode", m_version.EventingNamespace + "/DeliveryModes/Push");

                // Writer the notify to endpoint
                WriteEndpointRef(xmlWriter, subscriptionRequest.NotifyTo, "NotifyTo");

                xmlWriter.WriteEndElement(); // End Delivery

                // Write Expiration time
                if (subscriptionRequest.Expires != null)
                {
                    xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Expires", null);
                    xmlWriter.WriteString(subscriptionRequest.Expires.DurationString);
                    xmlWriter.WriteEndElement(); // End Expires
                }

                // Write Filter element specifying the event to subscribe to.
                xmlWriter.WriteStartElement(WsNamespacePrefix.Wse, "Filter", null);
                xmlWriter.WriteAttributeString("Dialect", m_version.WsdpNamespaceUri + "/Action");
                xmlWriter.WriteString(subscriptionRequest.SubscriptionType.NamespaceUri + "/" + subscriptionRequest.SubscriptionType.TypeName);
                xmlWriter.WriteEndElement(); // End Filter

                xmlWriter.WriteEndElement(); // End Subscribe

                smw.WriteSoapMessageEnd(xmlWriter);

                // Performance debuging
                timeDebuger.PrintElapsedTime("*****Write Body Took");

                // Performance debuging
                timeDebuger.PrintTotalTime(startTime, "***Subscribe Message Build Took");

                // Create an Http client and send Subscribe request
                WsHttpClient httpClient = new WsHttpClient(m_version);

                msg.Body = xmlWriter.ToArray();

                subscribeResponse = httpClient.SendRequest(msg, subscriptionRequest.EndpointAddress);

                // If a subscribe response is received process it and return expiration time the subscription manager
                // actually assigned.
                // If a parsing fault is received print exception and go on.
                DpwsEventSubscription response = null;
                if (subscribeResponse == null)
                {
                    System.Ext.Console.Write("");
                    System.Ext.Console.Write("Subscribe response is null.");
                    return(null);
                }
                else
                {
                    byte[] responseBytes = subscribeResponse.Body as byte[];

                    // It is ok for the service to return a 202 and a 0 length response
                    // if thi is the case just return null
                    if (responseBytes == null || responseBytes.Length == 0)
                    {
                        return(null);
                    }

                    System.Ext.Console.Write("");
                    System.Ext.Console.Write("Response From: " + subscriptionRequest.EndpointAddress.Host);
                    System.Ext.Console.Write(responseBytes);
                    try
                    {
                        response = ProcessSubscribeResponse(responseBytes, messageID);
                    }
                    catch (Exception e)
                    {
                        System.Ext.Console.Write("");
                        System.Ext.Console.Write("Subscription response parsing failed.");
                        System.Ext.Console.Write(e.Message);
                    }
                }

                return(response);
            }
        }
        internal static WsMessage GenerateFaultResponse(WsWsaHeader header, WsFaultType faultType, String details, ProtocolVersion version)
        {
            String   code    = String.Empty;
            String   subcode = String.Empty;
            String   reason  = String.Empty;
            WsPrefix extraNS = WsPrefix.Wse;

            string faultAddress = null;

            if (header.FaultTo != null)
            {
                faultAddress = header.FaultTo.Address.OriginalString;
            }

            if (faultAddress == null)
            {
                faultAddress = version.AnonymousUri;
            }

            switch (faultType)
            {
            case WsFaultType.ArgumentException:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = "ArgumentException";
                reason  = "One of the arguments provided to a method is not valid.";
                break;

            case WsFaultType.ArgumentNullException:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = "ArgumentNullException";
                reason  = "A null reference was passed to a method that does not accept it as a valid argument.";
                break;

            case WsFaultType.Exception:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = "Exception";
                reason  = "Errors occured during application execution.";
                break;

            case WsFaultType.InvalidOperationException:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = "InvalidOperationException";
                reason  = "A method call is invalid for the object's current state.";
                break;

            case WsFaultType.XmlException:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = "XmlException";
                reason  = "Syntax errors found during parsing.";
                break;

            case WsFaultType.WsaInvalidMessageInformationHeader:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wsa + ":InvalidMessageInformationHeader";
                reason  = "A message information header is not valid and cannot be processed.";
                break;

            case WsFaultType.WsaMessageInformationHeaderRequired:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wsa + ":MessageInformationHeaderRequired";
                reason  = "A required message Information header, To, MessageID, or Action, is not present";
                break;

            case WsFaultType.WsaDestinationUnreachable:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wsa + ":DestinationUnreachable";
                reason  = "No route can be determined to reach the destination role defined by the WS=Addressing To.";
                break;

            case WsFaultType.WsaActionNotSupported:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wsa + ":ActionNotSupported";
                reason  = "The [action] cannot be processed at the receiver.";
                break;

            case WsFaultType.WsaEndpointUnavailable:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = WsNamespacePrefix.Wsa + ":EndpointUnavailable";
                reason  = "The endpoint is unable to process the message at this time.";
                break;

            case WsFaultType.WseDeliverModeRequestedUnavailable:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wse + ":DeliverModeRequestedUnavailable";
                reason  = "The request delivery mode is not supported.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseInvalidExpirationTime:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wse + ":InvalidExpirationTime";
                reason  = "The expiration time requested is invalid.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseUnsupportedExpirationType:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wse + ":UnsupportedExpirationType";
                reason  = "Only expiration durations are supported.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseFilteringNotSupported:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wse + ":FilteringNotSupported";
                reason  = "Filtering is not supported.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseFilteringRequestedUnavailable:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wse + ":FilteringRequestedUnavailable";
                reason  = "The requested filter dialect is not supported.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseEventSourceUnableToProcess:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = WsNamespacePrefix.Wse + ":EventSourceUnableToProcess";
                reason  = "No explaination yet.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseUnableToRenew:
                code    = WsNamespacePrefix.Soap + ":Receiver";
                subcode = WsNamespacePrefix.Wse + ":UnableToRenew";
                reason  = "No explaination yet.";
                extraNS = WsPrefix.Wse;
                break;

            case WsFaultType.WseInvalidMessage:
                code    = WsNamespacePrefix.Soap + ":Sender";
                subcode = WsNamespacePrefix.Wse + ":InvalidMessage";
                reason  = "Message is not valid and cannot be processed.";
                extraNS = WsPrefix.Wse;
                break;
            }

            // Create the XmlWriter
            using (XmlMemoryWriter xmlWriter = XmlMemoryWriter.Create())
            {
                // Generate the fault Header
                WsWsaHeader faultHeader = new WsWsaHeader(
                    version.AddressingNamespace + "/fault", // Action
                    header.MessageID,                       // RelatesTo
                    faultAddress,                           // To
                    null, null, null);                      // ReplyTo, From, Any

                WsMessage msg = new WsMessage(faultHeader, null, extraNS, null, null);

                WsSoapMessageWriter smw = new WsSoapMessageWriter(version);
                smw.WriteSoapMessageStart(xmlWriter, msg);

                // Generate fault Body
                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Fault", null);

                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Code", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Value", null);
                xmlWriter.WriteString(code);
                xmlWriter.WriteEndElement(); // End Value
                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Subcode", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Value", null);
                xmlWriter.WriteString(subcode);
                xmlWriter.WriteEndElement(); // End Value
                xmlWriter.WriteEndElement(); // End Subcode
                xmlWriter.WriteEndElement(); // End Code

                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Reason", null);
                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Text", null);
                xmlWriter.WriteAttributeString("xml", "lang", "http://www.w3.org/XML/1998/namespace", "en-US");
                xmlWriter.WriteString(reason);
                xmlWriter.WriteEndElement(); // End Text
                xmlWriter.WriteEndElement(); // End Reason

                xmlWriter.WriteStartElement(WsNamespacePrefix.Soap, "Detail", null);
                xmlWriter.WriteString(details);
                xmlWriter.WriteEndElement(); // End Detail

                xmlWriter.WriteEndElement(); // End Fault

                smw.WriteSoapMessageEnd(xmlWriter);

                msg.Body = xmlWriter.ToArray();

                // Flush and close writer. Return stream buffer
                return(msg);
            }
        }