在运行时期间动态调用WCF服务

时间:2011-07-03 16:22:08

标签: wcf

我正在尝试动态调用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> 

注意邮件正文。

由于

1 个答案:

答案 0 :(得分:1)

我不知道你为什么要这么做,但是如果你想调用期望你请求SOAP请求的方法,你必须首先向你的客户提供消息合同:

[MessageContract(WrapperName="GetName")]
public class MessageContract
{
    [MessageBodyMember(Name="value")]
    public Person Person { get; set; }
}

你还需要类似的回应合同。

默认序列化使用从操作合同名称推断的包装器,但由于您没有提供服务合同,因此您的序列化程序不了解现有包装器,因为您必须手动提供此附加知识或重新定义您的服务,以便它不会期望包装元素(它也是通过消息合同完成的,并将IsWrapped属性设置为false)。