Created
March 24, 2017 13:37
-
-
Save Misiu/e84a6adfd2891265f7ecb88bc6201130 to your computer and use it in GitHub Desktop.
CustomTextMessageEncoder V4
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.ServiceModel.Channels; | |
using System.ServiceModel.Description; | |
using System.Xml; | |
namespace DokZastrzezoneV4 | |
{ | |
public class CustomTextMessageBindingElement : MessageEncodingBindingElement, IWsdlExportExtension | |
{ | |
private MessageVersion _msgVersion; | |
private string _mediaType; | |
private string _encoding; | |
private readonly XmlDictionaryReaderQuotas _readerQuotas; | |
CustomTextMessageBindingElement(CustomTextMessageBindingElement binding) | |
: this(binding.Encoding, binding.MediaType, binding.MessageVersion) | |
{ | |
_readerQuotas = new XmlDictionaryReaderQuotas(); | |
binding.ReaderQuotas.CopyTo(_readerQuotas); | |
} | |
public CustomTextMessageBindingElement(string encoding, string mediaType, | |
MessageVersion msgVersion) | |
{ | |
if (encoding == null) | |
throw new ArgumentNullException("encoding"); | |
if (mediaType == null) | |
throw new ArgumentNullException("mediaType"); | |
if (msgVersion == null) | |
throw new ArgumentNullException("msgVersion"); | |
_msgVersion = msgVersion; | |
_mediaType = mediaType; | |
_encoding = encoding; | |
_readerQuotas = new XmlDictionaryReaderQuotas(); | |
} | |
public CustomTextMessageBindingElement(string encoding, string mediaType) | |
: this(encoding, mediaType, MessageVersion.Soap12WSAddressing10) | |
{ | |
} | |
public CustomTextMessageBindingElement(string encoding) | |
: this(encoding, "text/xml") | |
{ | |
} | |
public CustomTextMessageBindingElement() | |
: this("UTF-8") | |
{ | |
} | |
public override MessageVersion MessageVersion | |
{ | |
get | |
{ | |
return _msgVersion; | |
} | |
set | |
{ | |
if (value == null) | |
throw new ArgumentNullException("value"); | |
_msgVersion = value; | |
} | |
} | |
public string MediaType | |
{ | |
get | |
{ | |
return _mediaType; | |
} | |
set | |
{ | |
if (value == null) | |
throw new ArgumentNullException("value"); | |
_mediaType = value; | |
} | |
} | |
public string Encoding | |
{ | |
get | |
{ | |
return _encoding; | |
} | |
set | |
{ | |
if (value == null) | |
throw new ArgumentNullException("value"); | |
_encoding = value; | |
} | |
} | |
// This encoder does not enforces any quotas for the unsecure messages. The | |
// quotas are enforced for the secure portions of messages when this encoder | |
// is used in a binding that is configured with security. | |
public XmlDictionaryReaderQuotas ReaderQuotas | |
{ | |
get | |
{ | |
return _readerQuotas; | |
} | |
} | |
#region IMessageEncodingBindingElement Members | |
public override MessageEncoderFactory CreateMessageEncoderFactory() | |
{ | |
return new CustomTextMessageEncoderFactory(MediaType, Encoding, MessageVersion); | |
} | |
#endregion | |
public override BindingElement Clone() | |
{ | |
return new CustomTextMessageBindingElement(this); | |
} | |
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context) | |
{ | |
if (context == null) | |
throw new ArgumentNullException("context"); | |
context.BindingParameters.Add(this); | |
return context.BuildInnerChannelFactory<TChannel>(); | |
} | |
public override bool CanBuildChannelFactory<TChannel>(BindingContext context) | |
{ | |
if (context == null) | |
throw new ArgumentNullException("context"); | |
return context.CanBuildInnerChannelFactory<TChannel>(); | |
} | |
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context) | |
{ | |
if (context == null) | |
throw new ArgumentNullException("context"); | |
context.BindingParameters.Add(this); | |
return context.BuildInnerChannelListener<TChannel>(); | |
} | |
public override bool CanBuildChannelListener<TChannel>(BindingContext context) | |
{ | |
if (context == null) | |
throw new ArgumentNullException("context"); | |
context.BindingParameters.Add(this); | |
return context.CanBuildInnerChannelListener<TChannel>(); | |
} | |
public override T GetProperty<T>(BindingContext context) | |
{ | |
if (typeof(T) == typeof(XmlDictionaryReaderQuotas)) | |
{ | |
return (T)(object)_readerQuotas; | |
} | |
else | |
{ | |
return base.GetProperty<T>(context); | |
} | |
} | |
#region IWsdlExportExtension Members | |
void IWsdlExportExtension.ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) | |
{ | |
} | |
void IWsdlExportExtension.ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) | |
{ | |
// The MessageEncodingBindingElement is responsible for ensuring that the WSDL has the correct | |
// SOAP version. We can delegate to the WCF implementation of TextMessageEncodingBindingElement for this. | |
TextMessageEncodingBindingElement mebe = new TextMessageEncodingBindingElement | |
{ | |
MessageVersion = _msgVersion | |
}; | |
((IWsdlExportExtension)mebe).ExportEndpoint(exporter, context); | |
} | |
#endregion | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics; | |
using System.IO; | |
using System.ServiceModel.Channels; | |
using System.Text; | |
using System.Xml; | |
namespace DokZastrzezoneV4 | |
{ | |
public class CustomTextMessageEncoder : MessageEncoder | |
{ | |
private CustomTextMessageEncoderFactory factory; | |
private XmlWriterSettings writerSettings; | |
private string contentType; | |
public CustomTextMessageEncoder(CustomTextMessageEncoderFactory factory) | |
{ | |
this.factory = factory; | |
writerSettings = new XmlWriterSettings(); | |
writerSettings.Encoding = Encoding.GetEncoding(factory.CharSet); | |
//writerSettings.ConformanceLevel = ConformanceLevel.Fragment; | |
//writerSettings.OmitXmlDeclaration = false; | |
contentType = string.Format("{0}; charset={1}", this.factory.MediaType, writerSettings.Encoding.HeaderName); | |
} | |
public override string ContentType | |
{ | |
get | |
{ | |
return contentType; | |
} | |
} | |
public override string MediaType | |
{ | |
get | |
{ | |
return factory.MediaType; | |
} | |
} | |
public override MessageVersion MessageVersion | |
{ | |
get | |
{ | |
return 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); | |
string incoming = Encoding.UTF8.GetString(buffer.Array, buffer.Offset, buffer.Count); | |
Console.WriteLine("Incoming message:"); | |
Console.WriteLine(incoming); | |
Console.WriteLine(); | |
return ReadMessage(stream, int.MaxValue); | |
} | |
public override Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) | |
{ | |
XmlReader reader = XmlReader.Create(stream); | |
var message = Message.CreateMessage(reader, maxSizeOfHeaders, MessageVersion); | |
return message; | |
} | |
public override ArraySegment<byte> WriteMessage(Message message, int maxMessageSize, BufferManager bufferManager, int messageOffset) | |
{ | |
Debug.WriteLine("MESSAGE:"); | |
Debug.WriteLine(message.ToString()); | |
MemoryStream ms = new MemoryStream(); | |
XmlDictionaryWriter w = XmlDictionaryWriter.CreateBinaryWriter(ms); | |
message.WriteMessage(w); | |
w.Flush(); | |
ms.Position = 0; | |
XmlDictionaryReader r = XmlDictionaryReader.CreateBinaryReader(ms, XmlDictionaryReaderQuotas.Max); | |
XmlDocument doc = new XmlDocument(); | |
doc.PreserveWhitespace = true; | |
doc.Load(r); | |
XmlNode binarySecurityToken = doc.GetElementsByTagName("o:BinarySecurityToken")[0]; | |
if (binarySecurityToken != null) | |
{ | |
XmlAttribute attr = doc.CreateAttribute("EncodingType"); | |
attr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"; | |
if (binarySecurityToken.Attributes != null) binarySecurityToken.Attributes.Append(attr); | |
} | |
XmlNode SecurityTokenReference = doc.GetElementsByTagName("o:SecurityTokenReference")[0]; | |
if (SecurityTokenReference != null) | |
{ | |
XmlAttribute attr = doc.CreateAttribute("wsse11", "TokenType", "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd"); | |
attr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"; | |
if (SecurityTokenReference.Attributes != null) SecurityTokenReference.Attributes.Append(attr); | |
} | |
XmlNode wsseReference = doc.GetElementsByTagName("o:Reference")[0]; | |
if (wsseReference != null) | |
{ | |
XmlAttribute attr = doc.CreateAttribute("ValueType"); | |
attr.Value = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"; | |
if (wsseReference.Attributes != null) wsseReference.Attributes.Append(attr); | |
} | |
ms = new MemoryStream(); | |
w = XmlDictionaryWriter.CreateBinaryWriter(ms); | |
doc.WriteTo(w); | |
w.Flush(); | |
ms.Position = 0; | |
r = XmlDictionaryReader.CreateBinaryReader(ms, XmlDictionaryReaderQuotas.Max); | |
Message newMessage = Message.CreateMessage(r, maxMessageSize, message.Version); | |
newMessage.Properties.CopyProperties(message.Properties); | |
Debug.WriteLine("NEW MESSAGE:"); | |
Debug.WriteLine(newMessage.ToString()); | |
ArraySegment<byte> messageBuffer; | |
int messageLength; | |
using (MemoryStream stream = new MemoryStream()) | |
{ | |
using (XmlWriter writer = XmlWriter.Create(stream, writerSettings)) | |
{ | |
newMessage.WriteMessage(writer); | |
} | |
var writeBuffer = stream.ToArray(); | |
messageBuffer = new ArraySegment<byte>(writeBuffer); | |
messageLength = (int)stream.Position; | |
} | |
int totalLength = messageLength + messageOffset; | |
byte[] totalBytes = bufferManager.TakeBuffer(totalLength); | |
Array.Copy(messageBuffer.Array, 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, writerSettings); | |
message.WriteMessage(writer); | |
writer.Close(); | |
} | |
public override bool IsContentTypeSupported(string contentType) | |
{ | |
if (base.IsContentTypeSupported(contentType)) | |
{ | |
return true; | |
} | |
if (contentType.Length == MediaType.Length) | |
{ | |
return contentType.Equals(MediaType, StringComparison.OrdinalIgnoreCase); | |
} | |
else | |
{ | |
if (contentType.StartsWith(MediaType, StringComparison.OrdinalIgnoreCase) | |
&& (contentType[MediaType.Length] == ';')) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.ServiceModel.Channels; | |
namespace DokZastrzezoneV4 | |
{ | |
public class CustomTextMessageEncoderFactory : MessageEncoderFactory | |
{ | |
private readonly MessageEncoder _encoder; | |
private readonly MessageVersion _version; | |
private readonly string _mediaType; | |
private readonly string _charSet; | |
internal CustomTextMessageEncoderFactory(string mediaType, string charSet, MessageVersion version) | |
{ | |
_version = version; | |
_mediaType = mediaType; | |
_charSet = charSet; | |
_encoder = new CustomTextMessageEncoder(this); | |
} | |
public override MessageEncoder Encoder | |
{ | |
get { return _encoder; } | |
} | |
public override MessageVersion MessageVersion | |
{ | |
get { return _version; } | |
} | |
internal string MediaType | |
{ | |
get { return _mediaType; } | |
} | |
internal string CharSet | |
{ | |
get { return _charSet; } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment