Link to home
Start Free TrialLog in
Avatar of SimonPrice3376
SimonPrice3376

asked on

XML Encoding not in WCF Response

I am working in a company where we are taking over the provision of a service, but writing is ourselves rather than having access to the original source code and need to match the output character for character so that this doesnt cause our clients any issues.

When sending an error response back it must have the xml encoding at the top as per the response below

<?xml version="1.0" encoding="UTF-8"?>

 <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

   <SOAP-ENV:Body>

     <SOAP-ENV:Fault>

       <faultcode>SOAP-ENV:Client</faultcode>

       <faultstring>HstException: The hash supplied does not match the hash generated for string:1234512312321</faultstring>

       <faultactor>{faultFactorHere}</faultactor>

     </SOAP-ENV:Fault>

   </SOAP-ENV:Body>

 </SOAP-ENV:Envelope>

Open in new window


I get everything but this
<?xml version="1.0" encoding="UTF-8"?>

Open in new window



My code currently looks like this

public void ProvideFault(Exception error, MessageVersion messageVersion, ref Message fault)
        {
            var faultException = new FaultException(error.Message);
            var messageFault = faultException.CreateMessageFault();

            var message = Message.CreateMessage(messageVersion, messageFault, null);
            
            var newMessageFormat = message.Properties.Encoder = new ErrorMessageFormatter(new CustomTextMessageEncoderFactory("text/xml", "UTF-8", MessageVersion.Soap11WSAddressing10));
            message.Properties.Encoder = newMessageFormat; // this should be adding the encoding, however is not
            fault = new ProposalMessage(message); //// This addes my prefixes and names spaces
        }

Open in new window


This is the rest of the code for ErrorMessageFormatter and the Factory

public class ErrorMessageFormatter : MessageEncoder
    {
        private CustomTextMessageEncoderFactory factory;
        private XmlWriterSettings writerSettings;
        private string contentType;

        public ErrorMessageFormatter(CustomTextMessageEncoderFactory factory)
        {
            this.factory = factory;

            this.writerSettings = new XmlWriterSettings { Encoding = Encoding.GetEncoding(factory.CharSet) };
            this.contentType = $"{this.factory.MediaType}; charset={this.writerSettings.Encoding.HeaderName}";
        }
        public override string ContentType => this.contentType;

        public override string MediaType => factory.MediaType;

        public override MessageVersion MessageVersion => this.factory.MessageVersion;

        public override Message ReadMessage(ArraySegment<byte> buffer, BufferManager bufferManager, string contentType)
        {
            byte[] msgContents = new byte[buffer.Count];
            Array.Copy(buffer.Array, buffer.Offset, msgContents, 0, msgContents.Length);
            bufferManager.ReturnBuffer(buffer.Array);

            MemoryStream stream = new MemoryStream(msgContents);
            return ReadMessage(stream, int.MaxValue);
        }

        public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)
        {
            XmlReader reader = XmlReader.Create(stream);
            return Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);
        }

        public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset)
        {
            MemoryStream stream = new MemoryStream();
            XmlWriter writer = XmlWriter.Create(stream, this.writerSettings);
            message.WriteMessage(writer);
            writer.Close();

            byte[] messageBytes = stream.GetBuffer();
            int messageLength = (int)stream.Position;
            stream.Close();

            int totalLength = messageLength + messageOffset;
            byte[] totalBytes = bufferManager.TakeBuffer(totalLength);
            Array.Copy(messageBytes, 0, totalBytes, messageOffset, messageLength);

            ArraySegment<byte> byteArray = new ArraySegment<byte>(totalBytes, messageOffset, messageLength);
            return byteArray;
        }

        public override void WriteMessage(Message message, Stream stream)
        {
            XmlWriter writer = XmlWriter.Create(stream, this.writerSettings);
            message.WriteMessage(writer);
            writer.Close();
        }
    }

Open in new window


public class CustomTextMessageEncoderFactory : MessageEncoderFactory
    {
        private MessageEncoder _encoder;
        private MessageVersion _version;
        private string _mediaType;
        private string _charSet;

        internal CustomTextMessageEncoderFactory(string mediaType, string charSet,
            MessageVersion version)
        {
            _version = version;
            _mediaType = mediaType;
            _charSet = charSet;
            _encoder = new ErrorMessageFormatter(this);
        }

        public override MessageEncoder Encoder => _encoder;

        public override MessageVersion MessageVersion => _version;

        internal string MediaType => _mediaType;

        internal string CharSet => _charSet;
    }

Open in new window


I would be grateful for some help on why the XML encoding and version inforamation are not coming through and how I can resolve this.
Avatar of ste5an
ste5an
Flag of Germany image

How do you intercept the SOAP message?
Avatar of SimonPrice3376
SimonPrice3376

ASKER

Hi Stephan,

I have passed this onto a colleague of mine now as I have been re-directed to work on another WCF issue, and he is using a custom encoder now, which isnt a perfect fit for our needs, but is starting to get to where we need to go.  Once I see the final solution I will post it here as an answer 
This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.