3 votes

Créer dynamiquement une référence de service et utiliser le service

Ce que je veux faire, c'est utiliser le lien de service "WSDL" du fichier de configuration et utiliser le service de manière programmatique, en prenant le nom de la méthode que je vais utiliser.

le fragment de code que j'utilise de manière statique et que j'exécute est le suivant,

ServiceName.serviceClientSoapClient= new ServiceName.serviceClientSoapClient();

string xmlStr = client.getValues();

Et le point final est,

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

Mais je veux que tout cela soit créé par programme, Par exemple, mon fichier de configuration,

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

Ensuite, je veux utiliser ce fichier de configuration, utiliser le service et obtenir des résultats.

J'ai regardé les liens suivants, mais ici, cela se fait par l'intermédiaire d'une structure de service unique. Je veux qu'il soit installé à partir du fichier de configuration.

Comment connecter par programme un client à un service WCF ? , Comment faire ? Utiliser le ChannelFactory

2voto

lucky Points 10247

Il serait préférable de créer une interface et de l'appliquer aux clients du service. De cette façon, vous devez spécifier les méthodes, les paramètres et les autres éléments requis dans les fichiers de configuration, ce qui devient difficile à gérer. De plus, vous ne pouvez pas utiliser les objets de résultat comme des classes de type connu.

Vous pouvez donc essayer quelque chose comme cela :

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

0voto

rene Points 14522

Si tout ce dont vous avez besoin, c'est d'un objet de communication WCF pour gérer les points d'extrémité RequestReply, la méthode suivante le fera pour vous.

Il prend un message de demande valide, un point d'arrivée et une action de savon et donne le xml brut qui a été retourné par le service.

Si vous voulez lui donner autre chose qu'un Message vous devrez mettre en œuvre une alternative pour IRequestChannel décoré des attributs ServiceContract et 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;
}

Pour utiliser la méthode ci-dessus, vous pouvez récupérer les deux paramètres dans le fichier de configuration ou utiliser des valeurs constantes :

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");

Notez que vous n'aurez besoin d'aucune autre configuration dans votre fichier de configuration au-delà :

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

Utilisez le WSDL du service pour déterminer la 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"/>

et en suivant sa route à travers son portType et son message, vous trouverez les types :

 <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>

à partir de laquelle vous pouvez construire la forme de la charge utile XML pour GetData :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X