0

Actually this issue continued with my previous question that's about SOAP message serialization doesn't allow to change the root name via XmlRoot, so I manually change the root name of the message by WCF message inspector (via IClientMessageInspector), here is the new problem that I have trapped.

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

and the client message inspector is implemented to revise the message. Please be noted that the problem is caused by the changing of the message tag:

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

everything is fine until here and the passed in request message is as below:

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

what I need is to change the <customer> tag and this is what BeforeSendRequest did. But when I break the call in the service operation, EvaluateCustomer, I found the parameter customer is null instead of a new customer instance, why? I ever implemented Customer class with IXmlSerializable and found that the ReadXml wasn't called if the class root tag was changed in SOAP message, why? And How I can implement the scenario so that the ReadXml can be called or the new passed-in service parameter (customer in above example) will no longer be null?

I tested above issue with ServiceHost and WSHttpBinding, wcf client is created with ChannelFactory, and message inspector is extended with Endpoint behavior.

Any hints is welcome and appreciated.

Community
  • 1
  • 1
jones
  • 317
  • 3
  • 13

1 Answers1

0

I believe you need to first decorate the 'Customer' class with a [DataContract] attribute. Setting the 'Name' part of that attribute to 'MyCustomer'.

Also remember to add [DataMember] to those members that are to be serialized.

GreatAndPowerfulOz
  • 1,767
  • 13
  • 19