Это решение (с использованием 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
}