Space disappears on transferring via wcf (xml)

喜欢而已 提交于 2021-02-08 10:16:30

问题


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

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'.

The WCF service uses MTOM message encoding.

Is this a known effect for xml or wcf in general?

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?


回答1:


UPDATE: Replaced answer since it is clear that you're using MTOM.

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.

  1. Don't use MTOM
  2. Add some prefix character that both sender and receiver know about and that the receiver can then strip off (like quotes, etc.).
  3. Use a message inspector and buffer the message

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.



来源:https://stackoverflow.com/questions/43639242/space-disappears-on-transferring-via-wcf-xml

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!