为什么我在更改消息标记名称时在wcf服务调用中得到null参数?

时间:2015-10-23 05:10:07

标签: c# wcf soap

实际上这个问题继续我的previous question关于SOAP消息序列化并不允许通过XmlRoot更改根名称,因此我通过WCF消息手动更改消息的根名称检查员(通过IClientMessageInspector),这是我遇到的新问题。

[ServiceContract]
public interface ICustomerService
{
    [OperationContract]
    bool EvaluateCustomer(Customer customer);
}

public class CustomerService : ICustomerService
{
    public bool EvaluateCustomer(Customer customer)
    {
        // Evaluation is here ...
    }
}

public class Customer
{
    public Customer() { }
    public Customer(string id, string name, int age)
    {
        ID = id;
        Name = name;
        Age = age;
    }
    public string ID { get; set; }
    public String Name { get; set; }
    public int Age { get; set; }
}

并实现客户端消息检查器以修改消息。请注意,问题是由更改消息标记引起的:

    public object BeforeSendRequest(ref Message request, IClientChannel channel)
    {           
        MemoryStream ms = new MemoryStream();
        XmlWriter xw = XmlWriter.Create(ms);
        request.WriteMessage(xw);
        xw.Flush();
        ms.Position = 0;
        string body = Encoding.UTF8.GetString(ms.ToArray());
        xw.Close();

        // There will be no problem if no change with the tag 
        body = body.Replace("<customer", "<MyCustomer");
        body = body.Replace("</customer>", "</MyCustomer>");

        ms = new MemoryStream(Encoding.UTF8.GetBytes(body));
        XmlDictionaryReader xdr = XmlDictionaryReader.CreateTextReader(ms, new XmlDictionaryReaderQuotas());
        Message newMessage = Message.CreateMessage(xdr, int.MaxValue, request.Version);

        newMessage.Properties.CopyProperties(request.Properties);
        request = newMessage;

        return null;
    }

在此之前一切正常,传入的请求消息如下:

<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
  <s:Header>
    <a:Action s:mustUnderstand="1">http://tempuri.org/ITestService/EvaluateCustomer</a:Action>
    <a:MessageID>urn:uuid:b35ab229-129a-469b-9a54-be3eaae53e3a</a:MessageID>
    <a:ReplyTo>
      <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
    </a:ReplyTo>
  </s:Header>
  <s:Body>
    <EvaluateCustomer xmlns="http://tempuri.org/">
      <customer xmlns:d4p1="http://schemas.datacontract.org/2004/07/WcfTest" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
        <d4p1:Age>43</d4p1:Age>
        <d4p1:ID>No2</d4p1:ID>
        <d4p1:Name>Jones</d4p1:Name>
      </customer>
    </EvaluateCustomer>
  </s:Body>
</s:Envelope>

我需要的是更改<customer>标签,这就是BeforeSendRequest所做的。但是当我在服务操作EvaluateCustomer中断调用时,我发现参数customer是null而不是新的客户实例,为什么?我用IXmlSerializable实现了Customer类,发现如果在SOAP消息中更改了类根标记,则不会调用ReadXml,为什么?以及如何实现方案以便可以调用ReadXml或新的传入服务参数(上例中的客户)将不再为空?

我使用ServiceHost和WSHttpBinding测试了上述问题,使用ChannelFactory创建了wcf客户端,并使用Endpoint行为扩展了消息检查器。

欢迎并赞赏任何提示。

1 个答案:

答案 0 :(得分:0)

我相信你需要先装饰顾客&#39;具有[DataContract]属性的类。设置&#39;名称&#39;属于&#39; MyCustomer&#39;。

的部分属性

还要记住将[DataMember]添加到要序列化的成员中。