2011-07-03 43 views
0

我正在尝试动态调用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实体将被弹出ulated和正确的经营合同要执行的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

我不知道你为什么做这个硬盘的方式,但如果你想打电话给你显示你必须先提供消息的合同到客户端的方法期待SOAP请求:

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

而且您还需要类似的响应合同。

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

+0

谢谢拉迪斯拉夫,这很有道理...... – lihnid