26 votes

Comment appeler un service web sans wsdl dans .net

Je dois me connecter à un service web tiers qui ne fournit ni wsdl ni asmx. L'url du service est juste http://server/service.soap

J'ai lu cet article sur les appels de services bruts, mais je ne suis pas sûr que cela corresponde à ce que je recherche.

J'ai également demandé des fichiers wsdl, mais on m'a répondu qu'il n'y en avait pas (et qu'il n'y en aurait pas).

J'utilise C# avec .net 2.0, et je ne peux pas passer à la 3.5 (donc pas encore de WCF). Je pense que cette tierce partie utilise java, car c'est l'exemple qu'elle a fourni.

Merci d'avance !

MISE À JOUR Obtenir cette réponse lors de la consultation de l'url :

<SOAP-ENV:Envelope>
<SOAP-ENV:Body>
<SOAP-ENV:Fault>
<faultcode>SOAP-ENV:Server</faultcode>
<faultstring>
Cannot find a Body tag in the enveloppe
</faultstring>
</SOAP-ENV:Fault>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

26voto

MaLKaV_eS Points 663

J'ai finalement réussi à faire fonctionner ce système, et je vais donc écrire ici le code que j'utilise. (Rappelez-vous, .Net 2.0, et pas de wsdl à obtenir du service web).

Tout d'abord, nous créons un HttpWebRequest :

public static HttpWebRequest CreateWebRequest(string url)
{
    HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
    webRequest.Headers.Add("SOAP:Action");
    webRequest.ContentType = "text/xml;charset=\"utf-8\"";
    webRequest.Accept = "text/xml";
    webRequest.Method = "POST";
    return webRequest;
}

Ensuite, nous appelons le webservice en lui transmettant toutes les valeurs nécessaires. Comme je lis l'enveloppe de savon à partir d'un document xml, je vais traiter les données comme un StringDictionary. Il devrait y avoir une meilleure façon de faire, mais j'y réfléchirai plus tard :

public static XmlDocument ServiceCall(string url, int service, StringDictionary data)
{
    HttpWebRequest request = CreateWebRequest(url);

    XmlDocument soapEnvelopeXml = GetSoapXml(service, data);

    using (Stream stream = request.GetRequestStream())
    {
        soapEnvelopeXml.Save(stream);
    }

    IAsyncResult asyncResult = request.BeginGetResponse(null, null);

    asyncResult.AsyncWaitHandle.WaitOne();

    string soapResult;
    using (WebResponse webResponse = request.EndGetResponse(asyncResult))
    using (StreamReader rd = new StreamReader(webResponse.GetResponseStream()))
    {
        soapResult = rd.ReadToEnd();
    }

    File.WriteAllText(HttpContext.Current.Server.MapPath("/servicios/" + DateTime.Now.Ticks.ToString() + "assor_r" + service.ToString() + ".xml"), soapResult);

    XmlDocument resp = new XmlDocument();

    resp.LoadXml(soapResult);

    return resp;
}

Voilà, c'est tout. Si quelqu'un pense que GetSoapXml doit être ajouté à la réponse, je le noterai.

16voto

John Saunders Points 118808

À mon avis, il n'y a aucune raison pour qu'un service web SOAP ne fournisse pas de WSDL. Il n'est pas nécessaire qu'il soit généré dynamiquement par le service ; il n'est pas nécessaire qu'il soit disponible sur l'internet. Mais il n'est pas nécessaire que le WSDL soit généré dynamiquement par le service. doit soit un WSDL, même s'ils doivent vous l'envoyer sur un disquette clé USB !

Si vous avez la possibilité de vous plaindre auprès des fournisseurs de ce service, je vous invite à le faire. Si vous avez la possibilité de réagir, faites-le. Idéalement, changez de fournisseur de services et dites-leur que c'est parce qu'ils n'ont pas fourni de WSDL. À tout le moins, cherchez à savoir pourquoi ils ne pensent pas que c'est important.

5voto

Andrej Benedik Points 31

J'ai créé la méthode d'aide suivante pour appeler le service Web manuellement sans aucune référence :

public static HttpStatusCode CallWebService(string webWebServiceUrl, 
                                            string webServiceNamespace, 
                                            string methodName, 
                                            Dictionary<string, string> parameters, 
                                            out string responseText)
{
    const string soapTemplate = 
@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
   xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" 
   xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"">
  <soap:Body>
    <{0} xmlns=""{1}"">
      {2}    </{0}>
  </soap:Body>
</soap:Envelope>";

    var req = (HttpWebRequest)WebRequest.Create(webWebServiceUrl);
    req.ContentType = "application/soap+xml;";
    req.Method = "POST";

    string parametersText;

    if (parameters != null && parameters.Count > 0)
    {
        var sb = new StringBuilder();
        foreach (var oneParameter in parameters)
            sb.AppendFormat("  <{0}>{1}</{0}>\r\n", oneParameter.Key, oneParameter.Value);

        parametersText = sb.ToString();
    }
    else
    {
        parametersText = "";
    }

    string soapText = string.Format(soapTemplate, methodName, webServiceNamespace, parametersText);

    using (Stream stm = req.GetRequestStream())
    {
        using (var stmw = new StreamWriter(stm))
        {
            stmw.Write(soapText);
        }
    }

    var responseHttpStatusCode = HttpStatusCode.Unused;
    responseText = null;

    using (var response = (HttpWebResponse)req.GetResponse())
    {
        responseHttpStatusCode = response.StatusCode;

        if (responseHttpStatusCode == HttpStatusCode.OK)
        {
            int contentLength = (int)response.ContentLength;

            if (contentLength > 0)
            {
                int readBytes = 0;
                int bytesToRead = contentLength;
                byte[] resultBytes = new byte[contentLength];

                using (var responseStream = response.GetResponseStream())
                {
                    while (bytesToRead > 0)
                    {
                        // Read may return anything from 0 to 10. 
                        int actualBytesRead = responseStream.Read(resultBytes, readBytes, bytesToRead);

                        // The end of the file is reached. 
                        if (actualBytesRead == 0)
                            break;

                        readBytes += actualBytesRead;
                        bytesToRead -= actualBytesRead;
                    }

                    responseText = Encoding.UTF8.GetString(resultBytes);
                    //responseText = Encoding.ASCII.GetString(resultBytes);
                }
            }
        }
    }

    // standard responseText: 
    //<?xml version="1.0" encoding="utf-8"?>
    //<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    //    <soap:Body>
    //        <SayHelloResponse xmlns="http://tempuri.org/">
    //            <SayHelloResult>Hello</SayHelloResult>
    //        </SayHellorResponse>
    //    </soap:Body>
    //</soap:Envelope>
    if (!string.IsNullOrEmpty(responseText))
    {
        string responseElement = methodName + "Result>";
        int pos1 = responseText.IndexOf(responseElement);

        if (pos1 >= 0)
        {
            pos1 += responseElement.Length;
            int pos2 = responseText.IndexOf("</", pos1);

            if (pos2 > pos1)
                responseText = responseText.Substring(pos1, pos2 - pos1);
        }
        else
        {
            responseText = ""; // No result
        }
    }

    return responseHttpStatusCode;
}

Vous pouvez alors simplement appeler n'importe quelle méthode de service web avec le code suivant :

var parameters = new Dictionary<string, string>();
parameters.Add("name", "My Name Here");

string responseText;
var responseStatusCode = CallWebService("http://localhost/TestWebService.asmx", 
                                        "http://tempuri.org/", 
                                        "SayHello", 
                                        parameters, 
                                        out responseText);

3voto

Glen Points 13521

Si vous avez de la chance, vous pourrez toujours obtenir le wsdl. Certains frameworks de services web permettent de récupérer un WSDL généré dynamiquement.

Les services Web écrits avec Axis1.x permettent de récupérer un fichier WSDL généré dynamiquement en accédant à l'URL.

Il suffit de naviguer vers

http://server/service.soap/?wsdl

Je ne sais pas si c'est possible avec d'autres frameworks.

3voto

Keith Points 324

Hmm, c'est une question délicate mais pas impossible, mais je vais faire de mon mieux pour l'expliquer.

Voici ce qu'il faut faire

  1. Créez des classes sérialisables qui correspondent aux schémas d'objets que vous utilisez sur le service tiers.
  2. Vérifier s'ils utilisent des SOAPAction dans leurs appels de service.
  3. Voyez si vous pouvez créer un asmx qui imite leur service en termes de gestion des demandes et des réponses (ce qui sera utile pour tester votre application client si leur service est indisponible).
  4. Vous pouvez alors créer un proxy de service à partir de votre service fictif et modifier l'url du service lorsque vous appelez le service tiers.
  5. Si quelque chose ne fonctionne pas dans votre client, vous pouvez modifier votre service fictif, générer à nouveau le proxy et réessayer.

J'essaierai d'en ajouter d'autres au fur et à mesure que j'y penserai, mais cela devrait suffire à vous mettre sur la voie.

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