2017-12-18 353 views
2

我想要做的是;我使用配置文件中的“WSDL”服务链接并以编程方式使用服务,并使用我将使用的方法的名称。动态创建服务参考和使用服务

的代码片段我使用静态运行如下,

ServiceName.serviceClientSoapClient= new ServiceName.serviceClientSoapClient(); 

string xmlStr = client.getValues(); 

和端点是,

<endpoint address="http://someservice.com/Service.asmx" 
     binding="basicHttpBinding" bindingConfiguration="serviceClientSoap" 
     contract="ServiceName.serviceClientSoap" name="serviceClientSoap" /> 

但是,我想这一切的编程方式创建, 例如;我的配置文件,

<add key="serviceLink" value="http://someservice.com/Service.asmx"/> 
<add key="serviceClientClassName" value="serviceClientSoapClient"/> 
<add key="serviceMethod" value="getValues"/> 

然后我想使用这个配置文件,并使用服务,得到结果。

我看了下面的链接,但是这里是通过一个服务结构完成的。我希望它从配置文件安装。

How to programmatically connect a client to a WCF service? How to: Use the ChannelFactory

+0

你每个端点都有一个接口(你可以配置这些接口或者有一种方法来识别它们)?或者你总是期望响应的主体被返回为一个字符串? – rene

+0

它正在返回xml文件。当xml文件到达时,我动态地设置下一个进程。我在这一点上没有问题。不幸的是,这些端点没有接口。无论如何,我认为真正的问题在这里。 @rene –

回答

2

它可以更好地创建一个接口,并实现它的服务客户。通过这种方式,您应该指定配置文件中所需的方法,参数和其他内容,并且难以管理。另外,您不能将结果对象用作已知的类型类。

所以,你可以尝试这样的事情:

var url = ConfigurationManager.AppSettings["serviceLink"]; 
var serviceClientClassName = ConfigurationManager.AppSettings["serviceClientClassName"]; 
var serviceMethod = ConfigurationManager.AppSettings["serviceMethod"]; 
var endpoint = new EndpointAddress(new Uri(url)); 
//Specify the assembly of services library. I am assuming that the services are stored in the Executing Assembly 
var serviceClient = Assembly.GetExecutingAssembly().GetTypes() 
    .FirstOrDefault(x => x.Name == serviceClientClassName);//Find the service client type 
var instance = Activator.CreateInstance(serviceClient); //Create a new instance of type 
var methodInfo = serviceClient.GetMethod(serviceMethod); //Get method info 
var result = methodInfo.Invoke(instance, new object[] {}); // Invoke it 
+0

现在,我添加并运行该服务作为参考。但是如果我可以在运行时添加服务,那么一切都将是动态的。但现在,您的解决方案正在发挥作用。 @雨人 –

0

如果你需要的是WCF CommunicationObject的处理RequestReply端点,下面的方法会为你做的。

它需要一个有效的请求消息,端点和一个soapaction,并给出服务返回的原始xml。

如果您想给它其他任何东西然后Message您需要实现替代IRequestChannel用ServiceContract和OperationContract属性装饰。

// give it a valid request message, endpoint and soapaction 
static string CallService(string xml, string endpoint, string soapaction) 
{ 
    string result = String.Empty; 

    var binding = new BasicHttpBinding(); 

    // create a factory for a given binding and endpoint 
    using (var client = new ChannelFactory<IRequestChannel>(binding, endpoint)) 
    { 
     var anyChannel = client.CreateChannel(); // Implements IRequestChannel 

     // create a soap message 
     var req = Message.CreateMessage(
      MessageVersion.Soap11, 
      soapaction, 
      XDocument.Parse(xml).CreateReader()); 

     // invoke the service 
     var response = anyChannel.Request(req); 

     // assume we're OK 
     if (!response.IsFault) 
     { 
      // get the body content of the reply 
      var content = response.GetReaderAtBodyContents(); 
      // convert to string 
      var xdoc = XDocument.Load(content.ReadSubtree()); 
      result = xdoc.ToString(); 
     } 
     else 
     { 
      //throw or handle 
      throw new Exception("panic"); 
     } 
    } 
    return result; 
} 

要使用上面的方法,你可以从配置文件中获取两个参数,或使用一些常数值:

var result = CallService(
    @"<GetData xmlns=""http://tempuri.org/""><value>42</value></GetData>", 
    ConfigurationManager.AppSettings["serviceLink"], 
    ConfigurationManager.AppSettings["serviceSoapAction"]); 

// example without using appSettings 
var result2 = CallService(
    @"<GetValues xmlns=""http://tempuri.org/""></GetValues>", 
    "http://localhost:58642/service.svc", 
    "http://tempuri.org/IService/GetValues"); 

请注意,您将不再需要在你的配置文件中的任何其他配置超越:

<appSettings> 
    <add key="serviceLink" value="http://localhost:58642/service.svc"/> 
    <add key="serviceSoapAction" value="http://tempuri.org/IService/GetData"/> 
</appSettings> 

使用服务的WSDL找出的SOAPAction:

<wsdl:binding name="BasicHttpBinding_IService" type="tns:IService"> 
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http"/> 
    <wsdl:operation name="GetData"> 
     <soap:operation soapAction="http://tempuri.org/IService/GetData" style="document"/> 

,并按照通过其端口类型和消息它的路线,你会发现类型:

<wsdl:types> 
    <xs:schema elementFormDefault="qualified" targetNamespace="http://tempuri.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
     <xs:import namespace="http://schemas.datacontract.org/2004/07/"/> 
     <xs:element name="GetData"> 
     <xs:complexType> 
      <xs:sequence> 
      <xs:element minOccurs="0" name="value" type="xs:int"/> 
      </xs:sequence> 
     </xs:complexType> 
     </xs:element> 

,从中可以构建XML负载的形状的GetData:

<GetData xmlns="http://tempuri.org/"> 
    <value>42</value> 
</GetData>