通过wcf(xml)转移时空间消失

时间:2017-04-26 16:00:50

标签: c# xml wcf

我有一个对象A,其中包含我在WCF中传输模型(通信)的属性Name

[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "p0", Order = 0)]
public string Name { get; set; }

我发现当Name以空格开头时#39} 123'然后在另一方面反序列化后,它已经失去了空间,它变成了“123”。

WCF服务使用MTOM消息编码。

这通常是对xml或wcf的已知效果吗?

在提供的答案的帮助下,我发现由于Mtom编码而删除了前导空格。实际上,当我删除Mtom时,前导空格被正确传输。

安全配置在我的方案中没有任何作用。

有没有办法避免它?

1 个答案:

答案 0 :(得分:1)

更新:替换了答案,因为很明显您使用的是MTOM。

显然,这是WCF中的bug,根据this标记为“已延期”。所以很难说它何时会被修复。最后一个链接还提到了一些解决方法,我将在这里重现,以便它们不会迷路。

  1. 请勿使用MTOM
  2. 添加一些发件人和收件人都知道的前缀字符,然后接收器可以剥离(如引号等)。
  3. 使用消息检查器并缓冲消息
  4. 下面的代码显示了此问题的第三种解决方法:

    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();
        }
    }
    

    同样,真正的答案和代码来自here