简体   繁体   中英

WCF and encoding. Fails on german characters

This is the line that fails when passed into my wcf service (I've removed and swapped letters as this was an actual customers address, but left the offending characters in place).

<StreetAddress>TU Dasdfasdn, asdfa für adsf, htras-Bähr-trf. 1</StreetAddress>

Note the ü and ä characters. If I remove these characters from the address and send the XML to the service, it goes through fine.

I found one solution which works and involves recreating the incoming message as shown below:

Code Before

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
   buffer = request.CreateBufferedCopy(Int32.MaxValue); // FAILS HERE!!!
   var requestCopy = buffer.CreateMessage();       
   ... do stuff ....
   return null;
}

Code With Fix

public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
    var dictionaryReader = request.GetReaderAtBodyContents();
    var outerXml = dictionaryReader.ReadOuterXml();
    var parsedOuterXml = XElement.Parse(outerXml);
    var replacedRequest = Message.CreateMessage(request.Version, request.Headers.Action, parsedOuterXml);
    replacedRequest.Headers.CopyHeadersFrom(request.Headers);
    replacedRequest.Properties.CopyProperties(request.Properties);
    request = replacedRequest;


   buffer = request.CreateBufferedCopy(Int32.MaxValue); // NO LONGER FAILS HERE
   var requestCopy = buffer.CreateMessage();
    ..... do stuff .......
    return null
}

What doesn't make sense is that the address in the XML after the fix is EXACTLY the same, including the ü and ä characters. But this time my code runs fine and there are no errors.

The only thing I can think is that the call to XElement.Parse somehow fixes any encoding issues whereas CreateBufferedCopy won't, but thats just a guess.

Is there a 'proper' way to fix this? Has anyone come across this before? The 'fix' I found doesn't actually do anything as the XML before and after is the same (don't know why it works) and I would rather a more elegant solution, or at least an explanation of what is happening.

EDIT: Exception thrown is "Unexpected end of file. Following elements are not closed: Envelope. Line 105, position 3."

at System.Xml.XmlExceptionHelper.ThrowXmlException(XmlDictionaryReader reader, String res, String arg1, String arg2, String arg3)
   at System.Xml.XmlBufferReader.EnsureBytes(Int32 count)
   at System.Xml.XmlBufferReader.GetBuffer(Int32 count, Int32& offset)
   at System.Xml.XmlUTF8TextReader.ReadEndElement()
   at System.Xml.XmlUTF8TextReader.Read()
   at System.Xml.XmlBaseReader.MoveToContent()
   at System.Xml.XmlBaseReader.ReadEndElement()
   at System.ServiceModel.Channels.Message.ReadFromBodyContentsToEnd(XmlDictionaryReader reader, EnvelopeVersion envelopeVersion)
   at System.ServiceModel.Channels.ReceivedMessage.OnWriteBodyContents(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.Message.OnWriteMessage(XmlDictionaryWriter writer)
   at System.ServiceModel.Channels.Message.OnCreateBufferedCopy(Int32 maxBufferSize, XmlDictionaryReaderQuotas quotas)
   at System.ServiceModel.Channels.Message.CreateBufferedCopy(Int32 maxBufferSize)
   at Stella.ServiceLibrary.Security.MessageLogInspector.AfterReceiveRequest(Message& request, IClientChannel channel, InstanceContext instanceContext) in C:\Projects\SIHOT_CRES\WebServiceProjects\Stella.ServiceLibrary\Security\MessageLogInspector.cs:line 94

The problem seems to be that I was encoding a string which is inherently utf-16. So even though I was using

byte[] content = Encoding.UTF8.GetBytes(myXDocument.ToString());

Somehow, when it got to my service, it was still utf-16. Instead, I've had to use a XmlWriter with a memory stream and return as below

XmlWriterSettings writerSettings = new XmlWriterSettings {Encoding = Encoding.UTF8};
MemoryStream buffer = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(buffer, writerSettings))
{
    myXDocument.WriteTo(writer);
    writer.Flush();
    writer.Close();
    result = buffer.ToArray();
}
return result;

Result is now a byte[] encoded as utf-8 and now works with my service which expects utf-8

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM