2009-08-14 31 views
21

Tengo que conectarme a un servicio web de terceros que no proporciona wsdl ni asmx. La url del servicio es solo http://server/service.soapCómo llamar a un servicio web sin wsdl en .net

He leído this article sobre las llamadas a servicios sin procesar, pero no estoy seguro de si esto es lo que estoy buscando.

Además, he pedido archivos wsdl, pero me han dicho que no los hay (y que no los habrá).

Estoy usando C# con .net 2.0, y no puedo actualizar a 3.5 (por lo que aún no hay WCF). Creo que un tercero está usando Java, ya que ese es el ejemplo que han proporcionado.

¡Gracias de antemano!

ACTUALIZACIÓN Obtener esta respuesta cuando se navega por la 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> 
+0

Usted debe enviar una o más de los archivos de ejemplo de Java en algún lugar, luego publique el enlace aquí. Una posibilidad es http://snipt.org/. –

+0

He logrado conectar el servicio web, tan pronto como tenga un tiempo, publicaré cómo hacerlo. ¡Gracias por tu interés! –

Respuesta

20

Bueno, finalmente conseguí que esto funcionara, así que escribiré aquí el código que estoy usando. (Recuerde, .Net 2.0, y no wsdl para obtener del servicio web).

En primer lugar, crear 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; 
} 

A continuación, hacemos una llamada al servicio web, que pasa a lo largo de todos los valores necesarios. Mientras leo el sobre de jabón de un documento xml, manejaré los datos como StringDictionary. Debería ser una mejor manera de hacer esto, pero lo pensaré más tarde:

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

Así que, eso es todo. Si alguien piensa que se debe agregar GetSoapXml a la respuesta, lo anotaré.

+1

en mi humilde opinión, *** Creo que GetSoapXml debe agregarse a la respuesta, por favor, lo anotarás *** – Kiquenet

+0

Como puedes ver, esta es una pregunta de hace 8 años, así que es un poco complicado escribir GetSoapXml ahora como Ya no trabajo en la misma empresa, así que no tengo acceso al código. –

2

Si tiene suerte, aún se podía conseguir el WSDL. Algunos marcos de servicios web le permiten recuperar un WSDL generado dinámicamente.

Los servicios web escritos con Axis1.x le permiten recuperar un archivo WSDL generado dinámicamente navegando a la URL.

Simplemente navegar a

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

No sé si esto es posible con otros marcos sin embargo.

+0

Intenté esto, no funcionó. Gracias de todos modos :) –

+0

pensé que era un tiro lejano. ¿Conoces ese marco (si existe) en el que está escrito el servicio? Si no hay WSDL, ¿cómo se supone que debes usar este servicio? ¿Tienen alguna guía para ti? – Glen

+0

Han enviado algunos archivos .java como ejemplo, pero como no sé nada de Java ... –

3

Hmm, complicado aquí pero no imposible, pero haré todo lo posible para explicarlo.

Lo que necesitan hacer es

  1. crear clases serializables que coinciden con los esquemas de objeto que está tratando con el servicio de terceros.
  2. Averigüe si utilizan alguna SOAPAction en sus llamadas de servicio
  3. Vea si puede crear un asmx que imite su servicio en términos de poder manejar solicitudes y respuestas (esto será bueno para probar su aplicación cliente si su el servicio no funciona)
  4. Puede crear un servidor proxy de servicio desde su servicio ficticio y cambiar la URL del servicio cuando llame al servicio de un tercero.
  5. Si algo no funciona en su cliente, entonces puede modificar su servicio ficticio, volver a generar el proxy y volver a intentarlo.

Trataré de añadir más cuando lo pienso, pero eso debería ser suficiente para empezar.

+0

Buscaré información sobre esto, pero, por favor, publique cualquier información que considere útil. –

+0

Sí, espero que incluso tengan un esquema XML para esto. OTOH, si vas a hacer algo con un servicio ficticio, no hagas nada con ASMX, usa WCF. –

+0

¿Es WCF compatible con 2.0? Creo que solo se podía usar con 3.0 –

10

En mi opinión, no hay excusa para que un servicio web SOAP no proporcione un WSDL. No necesita ser generado dinámicamente por el servicio; no necesita estar disponible a través de Internet. Pero hay debe ser un WSDL, incluso si tienen que enviárselo en un disquete unidad de disco!

Si tiene alguna posibilidad de presentar una queja a los proveedores de este servicio, le insto a que lo haga. Si tiene la capacidad de retroceder, hágalo. Idealmente, cambie de proveedores de servicios y dígales a estas personas que es porque no proporcionaron un WSDL.Por lo menos, averigua por qué no creen que sea importante.

+0

El esquema XML para enviar y recuperar información está documentado. Lo único que me falta es el conocimiento para conectarme adecuadamente. En cuanto a la empresa que lo proporciona, es una compañía de seguros, por lo que no hay posibilidad de quejarse :( –

+1

En realidad, estoy totalmente en desacuerdo con eso. ¿Son estos esquemas parte de cualquier estándar de la industria, de una organización de estándares industriales (internacionales o no) Si es así, esto le da un único punto para seguir adelante, y una industria llena de otros desarrolladores que podrían unirse a usted para presionar. No es como si les pidiera que hagan algo muy complicado o costoso, especialmente si ya lo han hecho. un mecanismo para distribuir los esquemas. Incluso si es específico de la empresa, una vez que tienen los esquemas, el resto es bastante fácil. –

+0

¿Alguna suerte al descubrir por qué no quieren proporcionar un WSDL? Quizás debería obtener un prueba de XMLspy, y muéstreles qué fácil sería, dado que ya tienen los esquemas XML. –

1

He creado el siguiente método de ayuda para llamar WebService manualmente sin ninguna referencia:

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

continuación, puede simplemente llamar a cualquier método de servicio web con el siguiente código:

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); 
+0

Voy a probar esto: si funciona, será un misterio el motivo por el que solo recibiste un voto por turno. –

+0

Mi única extensión necesaria a lo anterior sería la inclusión de un SoapHeader .. –

Cuestiones relacionadas