2010-03-18 22 views
8

Estoy intentando usar un servicio web en una aplicación web C# ASP.Net. El servicio está construido en PHP y está ubicado en algún servidor remoto que no está bajo mi control, así que no puedo modificarlo para agregar metadatos o algo más.¿Cómo acceder a un servicio web PHP desde ASP.Net?

Cuando utilizo la opción "Agregar referencia Web" en Visual Studio 2008, recibo el siguiente error:

The HTML document does not contain Web service discovery information.

al intentar añadir el siguiente servicio web.

https://subreg.forpsi.com/robot2/subreg_command.php?wsdl

Las funciones de servicios web se exponen y se muestran en Visual Studio 2008. Sin embargo no pude agregar la referencia a la misma para su uso en ASP.Net aplicación.

t3Service" Description

Methods __construct ()

create_contact ()

get_contact ()

get_domain_info ()

get_last_error_code ()

get_last_error_msg ()

get_NSSET ()

get_owner_mail ()

login ()

register_domain ()

register_domain_with_admin_contacts ( )

renew_domain ()

request_sendmail ()

send_auth_info ()

transfer_domain ()

  1. También probé el método wsdl.exe recuperando el XML y lo copia a un archivo WSDL y genera una clase de proxy. Pero la salida wsdl contiene advertencias y la clase proxy generada salta las funciones expuestas y genera algo como esto:

    // CODEGEN: Se ignoró el enlace de la operación 'create_contact' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de operación 'get_contact' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de operación 'get_domain_info' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: Se ignoró el enlace de operación 'get_last_error_code' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de operación 'get_last_error_msg' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de operación 'get_NSSET' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de operación 'get_owner_mail' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de la operación 'send_auth_info' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de operación 'transfer_domain' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: Se ignoró el enlace de la operación 'request_sendmail' desde el espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró la operación de enlace 'inicio de sesión' desde el espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ignoró el enlace de la operación 'domain_registro' desde el espacio de nombres 'urna: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: se ha ignorado la operación que vincula 'register_domain_with_admin_contacts' desde el espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo. // CODEGEN: Se ignoró la operación que vincula 'renew_domain' del espacio de nombres 'urn: t3'. Cada parte del mensaje en un mensaje use = encoded debe especificar un tipo.

Editar:

probé este pedazo de código para mi clase codificado mano.

public String makeWebRequest(String methodName) 
     { 
       // Create the web request 
       HttpWebRequest request = WebRequest.Create("https://subreg.forpsi.com/robot2/subreg_command.php/") as HttpWebRequest; 
       // Add authentication to request 
       request.Credentials = new NetworkCredential("[email protected]", "bar"); 
       request.Method = "POST"; 
       request.ContentType = "text/xml"; 
       request.Headers.Add("SOAPAction: https://subreg.forpsi.com/robot2/subreg_command.php/" + methodName); 

      // Get response 
      using (HttpWebResponse response = request.GetResponse() as HttpWebResponse) 
      { 
       // Get the response stream 
       StreamReader reader = new StreamReader(response.GetResponseStream()); 
       // Console application output 
       //Console.WriteLine(reader.ReadToEnd()); 
       return reader.ReadToEnd(); 
      } 
     } 

Pero cuando trato de obtener una respuesta entonces se vuelve

The remote server returned an error: (500) Internal Server Error.

Respuesta

6

Como se menciona, tendrá que codificar manualmente su "proxy" para este servicio web.

Un ejemplo de realización manual de una llamada al servicio web - puede que tenga que modificar un poco el método.

private string MakeWebServiceCall(string methodName, string requestXmlString) 
     { 
      WebRequest webRequest = WebRequest.Create("https://subreg.forpsi.com/robot2/subreg_command.php"); 

      HttpWebRequest httpRequest = (HttpWebRequest)webRequest; 
      httpRequest.Method = "POST"; 
      httpRequest.ContentType = "text/xml"; 
      httpRequest.Headers.Add("SOAPAction: https://subreg.forpsi.com/robot2/subreg_command.php/" + methodName); 
      Stream requestStream = httpRequest.GetRequestStream(); 

      //Create Stream and Complete Request 
      StreamWriter streamWriter = new StreamWriter(requestStream); 
      streamWriter.Write(String.Format(this.GetSoapString(), requestXmlString)); 
      streamWriter.Close(); 

      //Get the Response 
      WebResponse webResponse = httpRequest.GetResponse(); 
      Stream responseStream = webResponse.GetResponseStream(); 
      StreamReader streamReader = new StreamReader(responseStream); 

      //Read the response into an xml document 
      System.Xml.XmlDocument soapResonseXMLDocument = new System.Xml.XmlDocument(); 
      soapResonseXMLDocument.LoadXml(streamReader.ReadToEnd()); 

      //return only the xml representing the response details (inner request) 
      return soapResonseXMLDocument.GetElementsByTagName(methodName + "Result")[0].InnerXml; 
     } 

Yo recomendaría la creación de xsd que pueden ser utilizados para generar objetos (usando xsd.exe) y luego se puede serializado respuestas/deserializar y solicitudes de objetos realidad.

EDIT: método GetSoapString()

private string GetSoapString() 
     { 
      StringBuilder soapRequest = new StringBuilder("<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""); 
      soapRequest.Append(" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" "); 
      soapRequest.Append("xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body>"); 
      soapRequest.Append("{0}"); 
      soapRequest.Append("</soap:Body></soap:Envelope>"); 
      return soapRequest.ToString(); 
     } 

Por Steve Referencia

Call uno parece:

<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
       xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
<soap:Body> 
<get_contact> 
<id>123</id> 
</get_contact> 
</soap:Body> 
</soap:Envelope> 

Respuesta:

<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:t3" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"> 
    <SOAP-ENV:Body> 
     <ns1:get_contactResponse> 
     <get_contactReturn xsi:type="xsd:boolean">false</get_contactReturn> 
     </ns1:get_contactResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 
+0

@Dan Muchas gracias por este fragmento de código. Realmente despejó mi pensamiento sobre el tema. Todo es bastante comprensible en su código. Pero no pude obtener/encontrar la función llamada * GetSoapString *.¿Podrías simplemente decir lo que hace para poder escribir uno propio o si ya está definido, entonces podrías darle implementación o .Net Namespace que concuerde con la definición para él? –

+0

@Dan Probé tu código. Pero cuando trato de obtener una respuesta del servidor, recibo lo siguiente: * El servidor remoto devolvió un error: (500) Error interno del servidor. * ¿Es normal? En caso afirmativo, ¿qué debo hacer en mi código para procesar dicha respuesta? Antes de publicar mi problema en stackoverflow, intenté con otro código e intenté enviar una solicitud web, pero se devolvió el mismo error. ¿Significa que requiere alguna autorización o credenciales? ¿Veo claramente una función Login() allí? ¿El SSL está creando el problema? Si debo enviar credenciales al servicio web, ¿cómo enviarlas? –

+0

@Dan * WebResponse webResponse = httpRequest.GetResponse(); * Esta es la línea donde se devuelve el error anterior. –

1

"servicio web" es un término muy genérico. Algunos tipos de servicios web pueden implementar un WSDL, pero no es un requisito. IIRC requiere una interfaz SOAP para proporcionar un WSDL, y tanto nuSOAP como la extensión SOAP de PHP son compatibles con WSDL. Por lo tanto, parece que el extremo remoto no se ha implementado correctamente.

0

Edición: Anteriormente recibí un error interno del servidor 500 porque mi secuencia de comandos no estaba formateada correctamente. Analicé el xml devuelto por el servicio web y construí mi mensaje de cadena de jabón mirando xml. Finalmente supere el problema con la ayuda de Dan^& un poco de investigación en internet. Gracias Dan.

I got over the 500 server error. Now i am able to get a response of login failure atleast...

public String MyWebServiceCall() 
     { 
      string strSoapMessage = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" 
      + "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:tns=\"http://www.artwork-systems.com/webway/sessions\" xmlns:types=\"http://www.artwork-systems.com/webway/sessions/encodedTypes\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" 
      + " <soap:Body soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" 
      + " <tns:Login>" 
      + " <login xsi:type=\"xsd:string\">[email protected]</login>" 
      + " <auth xsi:type=\"xsd:string\">bar</auth>" 
      + " </tns:Login>" 
      + " </soap:Body>" 
      + "</soap:Envelope>"; 

      HttpWebRequest req = (HttpWebRequest)WebRequest.CreateDefault(new Uri(@"https://subreg.forpsi.com/robot2/subreg_command.php/")); 

      req.ContentType = "text/xml; charset=UTF-8"; 
      req.Method = "POST"; 
      req.Accept = "text/xml"; 
      req.Headers.Add("SOAPAction", @"https://subreg.forpsi.com/robot2/subreg_command.php/"); 
      req.ProtocolVersion = HttpVersion.Version11; 
      req.Credentials = CredentialCache.DefaultCredentials; 
      //req.Credentials = new NetworkCredential("[email protected]", "bar"); 

      StreamWriter stm = new StreamWriter(req.GetRequestStream(), Encoding.ASCII); 
      stm.Write(strSoapMessage); 
      stm.Flush(); 
      stm.Close(); 

      HttpWebResponse wr = (HttpWebResponse)req.GetResponse(); 
      StreamReader srd = new StreamReader(wr.GetResponseStream()); 
      string resulXmlFromWebService = srd.ReadToEnd(); 
      return resulXmlFromWebService; 
     } 

Ahora, el siguiente problema es pasar las credenciales correctas y procesar la respuesta a hacer otras cosas ...

por cierto, aquí fue la respuesta ....

<?xml version="1.0" encoding="UTF-8"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:t3" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:loginResponse><loginReturn xsi:type="xsd:boolean">false</loginReturn></ns1:loginResponse></SOAP-ENV:Body></SOAP-ENV:Envelope> 

Editar: El valor falso es correcto, ya que estoy enviando las credenciales incorrectas. Llamo a otras funciones del servicio web de manera similar y pude llamar a todas las funciones del servicio web y recuperar los valores devueltos correspondientes y luego realizar otro procesamiento.

Gracias a todos los que ayudaron a contribuir a resolver el problema.

Saludos

Cuestiones relacionadas