Comment appeler un service web sans wsdl in.net
je dois me connecter à un service web tiers qui ne fournit ni wsdl ni asmx. L'url du service est tout simplement <!-2 http://server/service.savon
j'ai lu cet article à propos des appels de raw services, mais je ne suis pas sûr que ce soit ce que je cherche.
aussi, j'ai demandé des fichiers wsdl, mais on m'a dit qu'il n'y en avait pas (et qu'il n'y en aura pas).
j'utilise C# avec .net 2.0, et je ne peux pas passer à 3.5 (donc pas encore de WCF). Je pensez que le tiers utilise java, car c'est l'exemple qu'ils ont fourni.
Merci d'avance!
UPDATE Obtenir cette réponse lors de la navigation dans 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>
5 réponses
Eh bien, j'ai finalement obtenu que cela fonctionne, donc je vais écrire ici le code que j'utilise. (Rappelez-vous, .Net 2.0, et aucun wsdl pour 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 faisons un appel au service Web, en transmettant toutes les valeurs nécessaires. Pendant que je lis l'enveloppe soap d'un document xml, je traiterai les données comme un dictionnaire. Cela devrait être une meilleure façon de le 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;
}
Donc, c'est tout. Si quelqu'un pense que GetSoapXml doit être ajouté à la réponse, je l'écrirai.
à mon avis, il n'y a pas d'excuse 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 Internet. Mais il y a soyez un WSDL, même s'ils doivent vous l'envoyer sur un disquette clé usb!
si vous avez la possibilité de vous plaindre aux fournisseurs de ce service, alors je vous exhorte à le faire. Si vous avez la possibilité de repousser, alors faites-le. Idéalement, le service de commutation et dites à ces gens que c'est parce qu'ils n'ont pas fourni de WSDL. Au moins, trouvez pourquoi ils ne pensent pas que c'est important.
Hmm, difficile ici mais pas impossible mais je vais faire de mon mieux pour l'expliquer.
Ce que vous devez faire est de
- créez des classes sérialisables qui correspondent aux schémas d'objets que vous traitez sur le service tiers.
- savoir s'ils utilisent des SOAPAction dans leurs appels de service
- voir si vous pouvez créer un asmx qui imite leur service en termes de capacité à traiter les requêtes et les réponses (ce sera bon pour tester votre application client si leur service est en bas)
- vous pouvez alors créer un mandataire de service à partir de votre service fictif et changer l'url du service lorsque vous appelez le service d'un tiers.
- si quelque chose ne fonctionne pas chez votre client, alors vous pouvez modifier votre service fictif, générer de nouveau le proxy et essayer de nouveau.
je vais essayer d'ajouter plus comme et quand j'y pense, mais ce devrait être assez pour vous obtenir a commencé.
Si vous êtes chanceux, vous pouvez toujours obtenir le wsdl. Certains cadres de service web vous permettent de récupérer une WSDL générée dynamiquement.
Services Web écrits avec Axis1.x vous permet de récupérer un fichier WSDL généré dynamiquement en parcourant l'URL.
il suffit de parcourir à
http://server/service.soap/?wsdl
je ne sais pas si cela est possible avec d'autres cadres.
j'ai créé la méthode helper suivante pour appeler WebService 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);