WCF Change message encoding from Utf-16 to Utf-8 - wcf

I have a WCF connected service in a .net core application. I'm using the code that is autogenerated taken the wsdl definition.
Currently at the top of the request xml is including this line:
<?xml version="1.0" encoding="utf-16"?>
I can't find a simple way to change this encoding to UTF-8 when sending the request.
Since I could find a configuration option a the request/client objects, I've tried to change the message with following code at IClientMessageInspector.BeforeSendRequest
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
// Load a new xml document from current request
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(request.ToString());
((XmlDeclaration)xmlDocument.FirstChild).Encoding = Encoding.UTF8.HeaderName;
// Create streams to copy
var memoryStream = new MemoryStream();
var xmlWriter = XmlWriter.Create(memoryStream);
xmlDocument.Save(xmlWriter);
xmlWriter.Flush();
xmlWriter.Close();
memoryStream.Position = 0;
var xmlReader = XmlReader.Create(memoryStream);
// Create a new message
var newMessage = Message.CreateMessage(request.Version, null, xmlReader);
newMessage.Headers.CopyHeadersFrom(request);
newMessage.Properties.CopyProperties(request.Properties);
return null;
}
But the newMessage object still writes the xml declaration using utf-16. I can see it while debugging at the watch window since.
Any idea on how to accomplish this (should be) simple change will be very apreciated.

Which binding do you use to create the communication channel? The textmessageencoding element which has been contained in the CustomBinding generally contains TextEncoding property.
https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/textmessageencoding
WriteEncoding property specifies the character set encoding to be used for emitting messages on the binding. Valid values are
UnicodeFffeTextEncoding: Unicode BigEndian encoding
Utf16TextEncoding: Unicode encoding
Utf8TextEncoding: 8-bit encoding
The default is Utf8TextEncoding. This attribute is of type Encoding.
As for the specific binding, it contains the textEncoding property too.
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.basichttpbinding.textencoding?view=netframework-4.0
Feel free to let me know if there is anything I can help with.

Related

Why JAX-RS Response.fromResponse(anotherResponse) not copying the entity?

This is part of a JAX-RS server which receives a response from another server and sends the same response back to its client.
This copies the entity from anotherResponse to responseForClient:
Response responseForClient = Response.fromResponse(anotherResponse).entity(anotherResponse.readEntity(InputStream.class)).build();
This doesn't copy the entity:
Response responseForClient = Response.fromResponse(anotherResponse).build();
The second one should also work as JAX-RS Response.fromResponse() should copy the entity also.
Why setting the entity is required?
I am using RestEasy-3.0.
You have to consume the InputStream before calling fromResponse because it only will copy the response. The JAX-RS won't do it automatically, and if you provide the new instance to the client then the entity will not be consumed
See the documentation of fromResponse
public static Response.ResponseBuilder fromResponse(Response response)
Create a new ResponseBuilder by performing a shallow copy of an existing Response.
The returned builder has its own response headers but the header values are shared with the original Response instance. The original response entity instance reference is set in the new response builder.
Note that if the entity is backed by an un-consumed input stream, the reference to the stream is copied. In such case make sure to buffer the entity stream of the original response instance before passing it to this method.
Buffer the response reading the InputStream to a byte array
InputStream is = anotherResponse.readEntity(InputStream.class);
byte[] bytes = IOUtils.toByteArray(is);
ByteArrayInputStream in= new ByteArrayInputStream (bytes);
This code is equivalent to yours
Response responseForClient =
Response.fromResponse(anotherResponse).entity(in).build()

BizTalk 2010 WCF Remove processing instruction

I need to do download an XML file from a public website (http://www.tcmb.gov.tr/kurlar/201707/10072017.xml) to get exchange rates.
But I have a problem since the XML contains an xml-stylesheet processing instruction.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="isokur.xsl"?>
<Tarih_Date Tarih="07.07.2017" Date="07/07/2017" Bulten_No="2017/131" >
I use a WCF-Custom port with webHttpBindng and BizTalk REST starter kit from bLogical. Everything works fine, but when I try to parse the incoming xml, I get an error on that processing instruction.
System.Xml.XmlException: Processing instructions (other than the XML declaration) and DTDs are not supported. Line 2, position 2.
I'm not sure what the best way would be to fix this. I tried to follow this guide WCF Errors on XML Deserialization but it still fails when I try to access the message content using the CreateBufferedCopy method.
using (var readStream = new System.IO.MemoryStream())
{
using (var buffer = reply.CreateBufferedCopy(int.MaxValue))
{
buffer.WriteMessage(readStream);
}
readStream.Position = 0;
xdoc.Load(readStream);
}
Does anybody know how I can access the content of my message without actually parsing the XML? I'm just trying to find a way to either remove that line or make the parser ignore it.
I found the solution myself in the end. Instead of a message inspector, I created a Message Encoder based on the CustomTextMessageEncoder that you can find online.
In the ReadMessage method I just added a little bit of code
public override Message ReadMessage(System.IO.Stream stream, int maxSizeOfHeaders, string contentType)
{
XmlReaderSettings xsettings = new XmlReaderSettings();
xsettings.IgnoreProcessingInstructions = true;
XmlReader reader = XmlReader.Create(stream,xsettings);
return Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);
}

Saxon .Net read xml from stream

all examples show how to read an xml from an local file. But how do I read a xml from a url or a stream and process it further?
Example: http://www.oreillynet.com/xml/blog/2006/03/hello_saxon_on_net_an_aspnet_i.html
thanks in advance
Look for XsltExamples.cs in the saxon-resources download available on both Sourceforge and www.saxonica.com. The very first example seems to do what you are asking for.
public static void ExampleSimple1(String sourceUri, String xsltUri) {
// Create a Processor instance.
Processor processor = new Processor();
// Load the source document
XdmNode input = processor.NewDocumentBuilder().Build(new Uri(sourceUri));
// Create a transformer for the stylesheet.
XsltTransformer transformer = processor.NewXsltCompiler().Compile(new Uri(xsltUri)).Load();
// Set the root node of the source document to be the initial context node
transformer.InitialContextNode = input;
// Create a serializer
Serializer serializer = new Serializer();
serializer.SetOutputWriter(Console.Out);
// Transform the source XML to System.out.
transformer.Run(serializer);
}
Are you using an XmlDocument object for reading the XML? If so, you'll want XMLDocument.Load() method, which can take a file path or URL, TextReader or Stream as input.
Likewise, XDocument.Load()(msdn.microsoft.com/en-us/library/system.xml.linq.xdocument.load(v=vs.110).aspx) has a similar set of overloads.

How to deserialise a proto that was received as a byte[]

I am using the Spring.Rest framework.
If we receive a 402, the body will contain a proto which in turn will contain various error information.
The Exception raised on a 402 is an instance of Spring.Rest.Client.HttpClientErrorException.
The response within the exception is an instance of Spring.HttpResponseMessage.
The Body within the response is of type byte[].
This means I have a byte[] while the Deserialiser is expecting a Stream.
In order to deserialise the proto contained in the body I have done the following:
MemoryStream mStream = new MemoryStream();
mStream.Write(exception.Response.Body,0,exception.Response.Body.Length);
var proto = Serializer.Deserialize<XXXRestProtoException>(mStream);
when I inspect the proto returned, its properties are all null.
Is my approach correct, or do I need to do more before presenting the Stream to the Deserialize method?
We have confirmed that the proto definitions used on Client and Server are in sync and the body is well formed on the server.
The Stream produced by this code has the same length and contents as the given byte[], which in turn matches the content-length header.
If you Write to a stream, then the Position is left at the end of the stream; 2 simple options:
rewind the stream; between the Write and the Deserialize, put:
ms.Position = 0;
initialize the stream from the blob:
MemoryStream mStream = new MemoryStream(exception.Response.Body);
I'd usually use the latter.

How to edit WCF Message - WCF message interceptors

i'm having some problems implementing my WCF message interceptor. Basically i'm accessing the body contents and performing an xslt tranform over the nodeset to sort it alphabethicaly.
I've tested the XSLT stylesheet and it's working no problems. I write the result of the transform to a MemoryStream object and then attempt to recreate the message from the stream contents.
I examine the resulting stream using either a StreamReader or by loading it into an XmlDocument and i can see the the xml it contains it my expected result from the XSLT transform.
My problem occures when i try to recreate the message! I create an XmlReader based on the stream and use this as my body source for Message.CreateMessage(.....);
I cannot understand why i'm suddenly losing the "correct" contents in the stream when i could examine it and see a couple of statements earlier.
Help very much appreciated!
Full code of the method below:
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
MessageBuffer msgbuf = request.CreateBufferedCopy(int.MaxValue);
Message tmpMessage = msgbuf.CreateMessage();
XmlDictionaryReader xdr = tmpMessage.GetReaderAtBodyContents();
MemoryStream ms = new MemoryStream();
_compiledTransform.Transform(xdr,null,ms);
ms.Position = 0;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ms);
MemoryStream newStream = new MemoryStream();
xmlDoc.Save(newStream);
newStream.Position = 0;
//To debug contents of the stream
StreamReader sr = new StreamReader(newStream);
var temp = sr.ReadToEnd();
//At this point the XSLT tranforms has resulted in the fragment we want so all good!
XmlReaderSettings settings = new XmlReaderSettings();
settings.ConformanceLevel = ConformanceLevel.Fragment;
newStream.Position = 0;
XmlReader reader = XmlReader.Create(newStream,settings);
reader.MoveToContent();
//Reader seems to have lost the correct fragment!!! At least returned message does not contain correct fragment.
Message newMessage = Message.CreateMessage(request.Version, null, reader);
newMessage.Properties.CopyProperties(request.Properties);
request = newMessage;
return request;
}
I think your code works Griff. I've just plugged it into an existing an existing IDispatchMessageInspector implementation and it generated a good (transformed) message. I therefore suspect your problem lies elsewhere.
How are you establishing that the 'losing' the correct contents? Could whatever is inspecting the transformed message be reading the message prior to transformation by mistake?
Unless you are trying to correlate state with the BeforeSendReply method then you should be returning null instead of the request reference.