2011-08-11 12 views
0

データを送受信するWCFサービスがあり、すべてのutf-8クライアントで完全に動作します。WCFとOracle/Linux間のISO-8859-1エンコーディングの使用

しかし私の顧客の一人が、ISO-8859-1エンコーディングで動作するOracle 9i/Linuxコールでこのサービスにアクセスしようとしており、特殊文字に問題があります。

thisクライアントはLinuxであり、DLLをインストールできないため、私は提案されたソリューションを使用できません。

このシナリオに基づいて、誰でも私に別の解決策を提案できますか(クライアント、サービス、または両方の変更が関係する可能性があります)?

ありがとうございます。

答えて

2

このソリューション(CustomTextEncoderを使用)は、あなたのシナリオでも機能するはずですか? linuxクライアントはデータを送信し続けることができます(iso-8859-1など)。サーバーでのみ使用されているエンコーダーで読み取ることができます。その後、エンコーダーはクライアント(UTF-8またはiso-8859-1に再度)に応答をエンコードする方法を決定できます。

レスポンスがiso-8859-1にあるようにするには、コンテンツタイプヘッダーを適切な文字セットで更新するメッセージインスペクタなどが必要な場合もあります。

更新:ISO-8859-1

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 
} 
+1

を使用してカスタム・エンコーダ付きの例私はしませんでした(エンコーダはサンプルから正確なクラスであるサンプル、との答えを更新しました1文字でも変更できます)。 'CustomTextMessageBindingElement'に渡されたパラメータがあなたが持っていたバインディングと互換性があることを確認しなければなりません。 – carlosfigueira

関連する問題