EagleMl Web Service - Custom Classes and Overrides
This section describes some additional actions you should fulfill to make your work more effective.
Create a CustomTextMessageBindingElement class.
internal class CustomTextMessageBindingElement : MessageEncodingBindingElement, IWsdlExportExtension   {     #region Fields     private MessageVersion _msgVersion;     private string _mediaType;     private string _encoding;     private readonly XmlDictionaryReaderQuotas _readerQuotas;     #endregion     #region Properties     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; }     }     #endregion     #region Constructors     private 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.Soap11WSAddressing10)     {           }     public CustomTextMessageBindingElement(string encoding)       : this(encoding, "text/xml")     {           }     public CustomTextMessageBindingElement()       : this("UTF-8")     {     }     #endregion     #region Overrides     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;       return base.GetProperty<T>(context);     }     #endregion     #region IMessageEncodingBindingElement Members     public override MessageEncoderFactory CreateMessageEncoderFactory()     {       return new CustomTextMessageEncoderFactory(MediaType, Encoding, MessageVersion);     }     #endregion     #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.       var mebe = new TextMessageEncodingBindingElement { MessageVersion = _msgVersion };       ((IWsdlExportExtension)mebe).ExportEndpoint(exporter, context);     }     #endregion   }
The most important methods are:
public CustomTextMessageBindingElement(string encoding) and public CustomTextMessageBindingElement()
In these methods, set the default contentType and encoding (text/xml and UTF-8).
Create CustomTextMessageEncoderFactory and CustomTextMessageEncoder classes.
public class CustomTextMessageEncoderFactory : MessageEncoderFactory   {     private MessageEncoder encoder;     private MessageVersion version;     private string mediaType;     private string charSet;     internal CustomTextMessageEncoderFactory(string mediaType, string charSet,       MessageVersion version)     {       this.version = version;       this.mediaType = mediaType;       this.charSet = charSet;       this.encoder = new CustomTextMessageEncoder(this);     }     public override MessageEncoder Encoder     {       get       {         return this.encoder;       }     }     public override MessageVersion MessageVersion     {       get       {         return this.version;       }     }     internal string MediaType     {       get       {         return this.mediaType;       }     }     internal string CharSet     {       get       {         return this.charSet;       }     }   }
CustomTextMessageEncoderFactory is a support class. The CustomTextMessageEncoder class is as follows:
public class CustomTextMessageEncoder : MessageEncoder   {        private CustomTextMessageEncoderFactory factory;     private XmlWriterSettings writerSettings;     private string contentType;     public CustomTextMessageEncoder(CustomTextMessageEncoderFactory factory)     {       this.factory = factory;       this.writerSettings = new XmlWriterSettings();       this.writerSettings.Encoding = Encoding.GetEncoding(factory.CharSet);       this.contentType = string.Format("{0}; charset={1}",         this.factory.MediaType, this.writerSettings.Encoding.HeaderName);     }     public override string ContentType     {       get       {         return this.contentType;       }     }     public override string MediaType     {       get       {         return factory.MediaType;       }     }     public override MessageVersion MessageVersion     {       get       {         return this.factory.MessageVersion;       }     }     public override System.ServiceModel.Channels.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 System.ServiceModel.Channels.Message ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType)        {            try            {                XmlReader reader = XmlReader.Create(stream);                return System.ServiceModel.Channels.Message.CreateMessage(reader, maxSizeOfHeaders, this.MessageVersion);            }            catch (Exception e)            {                stream.Position = 0;                string value="";                using (var strreader = new StreamReader(stream, Encoding.UTF8))                {                    value = strreader.ReadToEnd();                }                if (value.Contains("<ERROR>"))                {                    int k = value.IndexOf("<ERROR>");                    value=value.Substring(k + 7);                    k = value.LastIndexOf("</ERROR>");                    if (k > 0)                    {                        value = value.Substring(0,k);                    }                }                               System.ServiceModel.FaultCode fc = new System.ServiceModel.FaultCode("Receiver");                System.ServiceModel.Channels.Message m = Message.CreateMessage(this.MessageVersion, fc, value, "fault");                return m;            }        }     public override ArraySegment<byte> WriteMessage(System.ServiceModel.Channels.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(System.ServiceModel.Channels.Message message, Stream stream)     {       XmlWriter writer = XmlWriter.Create(stream, this.writerSettings);       message.WriteMessage(writer);       writer.Close();     }     public override bool IsContentTypeSupported(string contentType)     {       if (contentType == "text/plain" || contentType== "text/xml")         return true;       return base.IsContentTypeSupported(contentType);     }       }
The CustomTextMessageEncoder class requires the following fixes:
- The content type fix should be made in the IsContentTypeSupported(string contentType) method. Fix possible incorrect contentTypes from EagleMlWebService.
- Non-soap messages processing fix. The fix should be made in the ReadMessage(Stream stream, int maxSizeOfHeaders, string contentType) method.
Add the GenerateUID() method which generates a unique correlationID.
// unique id generation     private static string GenerateUID()     {       long i = 1;       foreach (byte b in Guid.NewGuid().ToByteArray())       {         i *= ((int)b + 1);       }       return string.Format("{0:x}", i - DateTime.Now.Ticks).ToUpper();     }