在WCF和Oracle/Linux之间使用ISO-8859-1编码

在WCF和Oracle/Linux之间使用ISO-8859-1编码,wcf,oracle,utf-8,iso-8859-1,Wcf,Oracle,Utf 8,Iso 8859 1,我有一个WCF服务,可以发送/接收数据,并与我的所有utf-8客户端完美配合 但是,我的一个客户正在尝试使用Oracle 9i/Linux调用访问此服务,该调用使用ISO-8859-1编码,我们在特殊字符方面遇到了问题 我无法使用建议的解决方案,因为客户端是Linux,无法安装DLL 基于这种情况,是否有人可以向我推荐另一种解决方案(可能涉及客户机、服务或两者的更改) 提前感谢。该解决方案(使用CustomTextEncoder)也应该适用于您的场景?linux客户端可以继续随心所欲地发送数据(

我有一个WCF服务,可以发送/接收数据,并与我的所有utf-8客户端完美配合

但是,我的一个客户正在尝试使用Oracle 9i/Linux调用访问此服务,该调用使用ISO-8859-1编码,我们在特殊字符方面遇到了问题

我无法使用建议的解决方案,因为客户端是Linux,无法安装DLL

基于这种情况,是否有人可以向我推荐另一种解决方案(可能涉及客户机、服务或两者的更改)

提前感谢。

该解决方案(使用CustomTextEncoder)也应该适用于您的场景?linux客户端可以继续随心所欲地发送数据(即,在iso-8859-1中),而仅在服务器上使用的编码器将能够读取数据。然后,编码器可以决定如何将响应编码回客户端(再次是UTF-8或iso-8859-1)

如果您希望响应也在iso-8859-1中,您可能还需要消息检查器之类的东西来使用适当的字符集更新内容类型头

更新:使用ISO-8859-1的自定义编码器示例

公共类堆栈溢出\u 7033442
{
[服务合同]
公共接口测试
{
[经营合同]
字符串回显(字符串文本);
}
公共类服务:ITest
{
公共字符串回显(字符串文本)
{
返回文本;
}
}
公共静态无效测试()
{
string baseAddress=“http://“+Environment.MachineName+”:8000/服务”;
ServiceHost主机=新ServiceHost(类型(服务),新Uri(基地址));
CustomBinding=新的CustomBinding(
新的CustomTextMessageBindingElement(“iso-8859-1”、“text/xml”、MessageVersion.Soap11),
新的HttpTransportBindingElement());
AddServiceEndpoint(typeof(ITest),binding,“”);
host.Open();
Console.WriteLine(“主机已打开”);
字符串请求=@“
您好,我是阿诺
";
HttpWebRequest req=(HttpWebRequest)HttpWebRequest.Create(baseAddress);
请求方法=“POST”;
req.ContentType=“text/xml;charset=iso-8859-1”;
请求标题[“SOAPAction”]=“http://tempuri.org/ITest/Echo";
Stream reqStream=req.GetRequestStream();
Encoding Encoding=Encoding.GetEncoding(“iso-8859-1”);
byte[]reqBytes=编码.GetBytes(请求);
reqStream.Write(reqBytes,0,reqBytes.Length);
reqStream.Close();
HttpWebResponse resp=(HttpWebResponse)req.GetResponse();
WriteLine(“HTTP/{0}{1}{2}”,resp.ProtocolVersion,(int)resp.StatusCode,resp.StatusDescription);
foreach(分别在Headers.allkey中的变量头)
{
WriteLine(“{0}:{1}”,header,resp.Headers[header]);
}
如果(分别为ContentLength>0)
{
WriteLine(新的StreamReader(resp.GetResponseStream(),encoding.ReadToEnd());
}
控制台。写入(“按ENTER键关闭主机”);
Console.ReadLine();
host.Close();
}
#区域自定义文本消息编码器示例,逐字记录
公共类CustomTextMessageEncoder:MessageEncoder
{
私人CustomTextMessageEncoderFactory工厂;
私有XmlWriterSettings writerSettings;
私有字符串contentType;
公共CustomTextMessageEncoder(CustomTextMessageEncoderFactory工厂)
{
这个工厂=工厂;
this.writerSettings=新的XmlWriterSettings();
this.writerSettings.Encoding=Encoding.GetEncoding(factory.CharSet);
this.contentType=string.Format(“{0};字符集={1}”,
this.factory.MediaType、this.writerSettings.Encoding.HeaderName);
}
公共重写字符串ContentType
{
得到
{
返回this.contentType;
}
}
公共重写字符串MediaType
{
得到
{
返回factory.MediaType;
}
}
公共覆盖消息版本消息版本
{
得到
{
返回this.factory.MessageVersion;
}
}
公共重写消息ReadMessage(ArraySegment buffer、BufferManager、BufferManager、string contentType)
{
byte[]msgContents=新字节[buffer.Count];
复制(buffer.Array,buffer.Offset,msgContents,0,msgContents.Length);
bufferManager.ReturnBuffer(buffer.Array);
MemoryStream stream=新的MemoryStream(msgContents);
返回ReadMessage(流,int.MaxValue);
}
公共重写消息ReadMessage(Stream、int-maxSizeOfHeaders、string-contentType)
{
XmlReader=XmlReader.Create(流);
return Message.CreateMessage(reader,maxSizeOfHeaders,this.MessageVersion);
}
公共重写ArraySegment WriteMessage(消息消息消息、int-maxMessageSize、BufferManager-BufferManager、int-messageOffset)
{
MemoryStream stream=新的MemoryStream();
XmlWriter=XmlWriter.Create(流,this.writerSettings);
message.WriteMessage(编写器);
writer.Close();
byte[]messageBytes=stream.GetBuffer();
int messageLength=(int)stream.Position;
stream.Close();
int totalLength=消息长度+消息偏移量;
byte[]totalBytes=bufferManager.TakeBuffer(totalLength);
复制(messageBytes,0,totalBytes,messageOffset,messageLength);
ArraySegment byteArray=新的ArraySegment(总字节数、messageOffset、messageLength);
乘火车返回;
}
公共覆盖无效写消息(消息消息、流)
{
XmlWriter=XmlWriter.Create(str
public class StackOverflow_7033442
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        string Echo(string text);
    }

    public class Service : ITest
    {
        public string Echo(string text)
        {
            return text;
        }
    }

    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
        CustomBinding binding = new CustomBinding(
            new CustomTextMessageBindingElement("iso-8859-1", "text/xml", MessageVersion.Soap11),
            new HttpTransportBindingElement());
        host.AddServiceEndpoint(typeof(ITest), binding, "");
        host.Open();
        Console.WriteLine("Host opened");

        string request = @"<?xml version=""1.0"" encoding=""iso-8859-1""?>
<s:Envelope xmlns:s=""http://schemas.xmlsoap.org/soap/envelope/"">
  <s:Body>
    <Echo xmlns=""http://tempuri.org/"">
      <text>Hello áéíóú</text>
    </Echo>
  </s:Body>
</s:Envelope>";
        HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(baseAddress);
        req.Method = "POST";
        req.ContentType = "text/xml; charset=iso-8859-1";
        req.Headers["SOAPAction"] = "http://tempuri.org/ITest/Echo";
        Stream reqStream = req.GetRequestStream();
        Encoding encoding = Encoding.GetEncoding("iso-8859-1");
        byte[] reqBytes = encoding.GetBytes(request);
        reqStream.Write(reqBytes, 0, reqBytes.Length);
        reqStream.Close();

        HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
        Console.WriteLine("HTTP/{0} {1} {2}", resp.ProtocolVersion, (int)resp.StatusCode, resp.StatusDescription);
        foreach (var header in resp.Headers.AllKeys)
        {
            Console.WriteLine("{0}: {1}", header, resp.Headers[header]);
        }

        if (resp.ContentLength > 0)
        {
            Console.WriteLine(new StreamReader(resp.GetResponseStream(), encoding).ReadToEnd());
        }

        Console.Write("Press ENTER to close the host");
        Console.ReadLine();
        host.Close();
    }

    #region Custom Text Message Encoder sample, verbatim
    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 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();
        }
    }
    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;
            }
        }
    }
    public class CustomTextMessageBindingElement : MessageEncodingBindingElement, IWsdlExportExtension
    {
        private MessageVersion msgVersion;
        private string mediaType;
        private string encoding;
        private XmlDictionaryReaderQuotas readerQuotas;

        CustomTextMessageBindingElement(CustomTextMessageBindingElement binding)
            : this(binding.Encoding, binding.MediaType, binding.MessageVersion)
        {
            this.readerQuotas = new XmlDictionaryReaderQuotas();
            binding.ReaderQuotas.CopyTo(this.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");

            this.msgVersion = msgVersion;
            this.mediaType = mediaType;
            this.encoding = encoding;
            this.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")
        {
        }

        public override MessageVersion MessageVersion
        {
            get
            {
                return this.msgVersion;
            }

            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                this.msgVersion = value;
            }
        }


        public string MediaType
        {
            get
            {
                return this.mediaType;
            }

            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                this.mediaType = value;
            }
        }

        public string Encoding
        {
            get
            {
                return this.encoding;
            }

            set
            {
                if (value == null)
                    throw new ArgumentNullException("value");
                this.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 this.readerQuotas;
            }
        }

        #region IMessageEncodingBindingElement Members

        public override MessageEncoderFactory CreateMessageEncoderFactory()
        {
            return new CustomTextMessageEncoderFactory(this.MediaType,
                this.Encoding, this.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)this.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();
            mebe.MessageVersion = this.msgVersion;
            ((IWsdlExportExtension)mebe).ExportEndpoint(exporter, context);
        }

        #endregion
    }
    #endregion
}