我正在尝试动态调用WCF服务。我可以连接到服务并调用不需要任何参数的方法。
ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(this.ServiceBinding, this.EndPoint.Address);
IRequestChannel channel = factory.CreateChannel();
但是,我无法调用需要复合实体作为参数的操作合同。
以下代码用于实例化请求消息:
Message requestMessage = Message.CreateMessage(this.ServiceBinding.MessageVersion, contractNameSpace, new SimpleMessageBody(value));
SimpleMessageBody类中使用的值是使用DataContractSerializer的实体的序列化值。
<Person xmlns="http://schemas.datacontract.org/2004/07/WcfService.Test.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Name>John Smith</Name></Person>
运营合同
public string GetData(Person value)
{
using (MemoryStream ms = new MemoryStream())
{
value = new Person { Name = "John Smith" };
DataContractSerializer ser = new DataContractSerializer(typeof(Person));
ser.WriteObject(ms, value);
var result = UnicodeEncoding.UTF8.GetString(ms.ToArray());
}
return string.Format("You entered: {0}", value.Name);
}
实体
[DataContract]
public class Person
{
[DataMember]
public string Name { get; set; }
}
从以上createmessage代码生成以下SOAP消息:
<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/IService1/GetData</a:Action>
<a:MessageID>urn:uuid:cf78d5b7-333b-40eb-a71c-d81cb9c37b5d</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">http://localhost:52724/Service1.svc</a:To>
</s:Header>
<s:Body><Person xmlns="http://schemas.datacontract.org/2004/07/WcfService.Test.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Name>John Smith</Name></Person></s:Body>
</s:Envelope>
但是,为了填充Person实体并执行正确的操作协定,SOAP必须如下:
<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/IService1/GetData</a:Action>
<a:MessageID>urn:uuid:d49bd525-0f30-46fe-94fb-0248c2cb1ea2</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
</s:Header>
<s:Body>
<GetData xmlns="http://tempuri.org/">
<value xmlns:d4p1="http://schemas.datacontract.org/2004/07/WcfService.Test.Service" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:Name>John Smith</d4p1:Name>
</value>
</GetData>
</s:Body>
</s:Envelope>
请注意邮件正文。
由于
答案 0 :(得分:1)
我不知道你为什么要这么做,但是如果你想调用期望你请求SOAP请求的方法,你必须首先向你的客户提供消息合同:
[MessageContract(WrapperName="GetName")]
public class MessageContract
{
[MessageBodyMember(Name="value")]
public Person Person { get; set; }
}
你还需要类似的回应合同。
默认序列化使用从操作合同名称推断的包装器,但由于您没有提供服务合同,因此您的序列化程序不了解现有包装器,因为您必须手动提供此附加知识或重新定义您的服务,以便它不会期望包装元素(它也是通过消息合同完成的,并将IsWrapped
属性设置为false
)。