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.