通过 wcf (xml) 传输时空间消失 [英] Space disappears on transferring via wcf (xml)
问题描述
我有一个带有属性 Name
的对象 A
,我在 WCF 中使用它来传输模型(通信).
I have an object A
with property Name
that I use in WCF to transfer a model (communication).
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "p0", Order = 0)]
public string Name { get; set; }
我发现当 Name
以空格123"开头时,在另一侧反序列化后,它丢失了空格,变成了123".
I discoverd that when Name
starts with a space ' 123' then after deserialisation on the other side it has lost the space and it became '123'.
WCF 服务使用 MTOM 消息编码.
The WCF service uses MTOM message encoding.
这通常是 xml 或 wcf 的已知效果吗?
Is this a known effect for xml or wcf in general?
在提供的答案的帮助下,我发现由于 Mtom 编码,前导空格被删除.事实上,当我删除 Mtom 时,前导空格会正确传输.
With the help of the answer provided I discovered that leading whitespaces are removed due to the Mtom encoding. Indeed when I remove Mtom the leading whitespaces are correctly transferred.
安全配置在我的场景中没有发挥任何作用.
The security configuration did not play any role in my scenario.
有什么办法可以避免吗?
Is there some way to avoid it?
推荐答案
UPDATE:已替换答案,因为很明显您正在使用 MTOM.
UPDATE: Replaced answer since it is clear that you're using MTOM.
显然这是一个 bug,根据 this 被标记为延期".所以很难说,什么时候能修好.最后一个链接还提到了一些解决方法,我将在这里重现,以免他们迷路.
Apparently this is a bug in WCF, that according to this is marked as 'Deferred'. So it is hard say, when it will be fixed. The last link also mentions some workarounds, which I will reproduce here, so that they don't get lost.
- 不要使用 MTOM
- 添加一些发送方和接收方都知道的前缀字符,然后接收方可以删除(如引号等).
- 使用消息检查器并缓冲消息
以下代码显示了此问题的第三种解决方法:
The code below shows the third workaround for this issue:
public class Post_4cfd1cd6_a038_420d_8cb5_ec5a2628df1a
{
[ServiceContract]
public interface ITest
{
[OperationContract]
string Echo(string text);
}
public class Service : ITest
{
public string Echo(string text)
{
Console.WriteLine("In service, text = {0}", ReplaceControl(text));
return text;
}
}
static Binding GetBinding()
{
//var result = new WSHttpBinding(SecurityMode.None) { MessageEncoding = WSMessageEncoding.Text };
var result = new BasicHttpBinding() { MessageEncoding = WSMessageEncoding.Mtom };
return result;
}
static string ReplaceControl(string text)
{
StringBuilder sb = new StringBuilder();
foreach (var c in text)
{
if ((' ' <= c && c <= '~') && c != '\\')
{
sb.Append(c);
}
else
{
sb.AppendFormat("\\u{0:X4}", (int)c);
}
}
return sb.ToString();
}
public class MyInspector : IEndpointBehavior, IDispatchMessageInspector, IClientMessageInspector
{
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
}
public void Validate(ServiceEndpoint endpoint)
{
}
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
request = request.CreateBufferedCopy(int.MaxValue).CreateMessage();
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
reply = reply.CreateBufferedCopy(int.MaxValue).CreateMessage();
}
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
return null;
}
}
public static void Test()
{
string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
var endpoint = host.AddServiceEndpoint(typeof(ITest), GetBinding(), "");
endpoint.Behaviors.Add(new MyInspector());
host.Open();
Console.WriteLine("Host opened");
ChannelFactory<ITest> factory = new ChannelFactory<ITest>(GetBinding(), new EndpointAddress(baseAddress));
factory.Endpoint.Behaviors.Add(new MyInspector());
ITest proxy = factory.CreateChannel();
string input = "\t\tDoc1\tCase1\tActive";
string output = proxy.Echo(input);
Console.WriteLine("Input = {0}, Output = {1}", ReplaceControl(input), ReplaceControl(output));
Console.WriteLine("input == output: {0}", input == output);
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}
同样,真正的答案和代码来自 此处.
Again, real answer and code are from here.
这篇关于通过 wcf (xml) 传输时空间消失的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!