如何从ASP.Net访问PHP Web服务?

时间:2010-03-18 12:02:20

标签: c# php web-services wsdl

我正在尝试在C#ASP.Net Web应用程序中使用Web服务。该服务是用PHP构建的,位于一些不受我控制的远程服务器上,因此我无法对其进行修改以将元数据或其他内容添加到其中。

当我在Visual Studio 2008中使用“添加Web引用”选项时, 我收到以下错误:

  

HTML文档不包含Web   服务发现信息。

尝试添加以下Web服务时。

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

Web服务功能在Visual Studio 2008中公开并显示。但是我无法添加对它的引用以便在ASP.Net应用程序中使用。

  

t3Service“说明

     

方法   __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. 我还尝试了wsdl.exe方法,检索xml并将其复制到wsdl文件并生成代理类。但是wsdl输出包含警告,生成的代理类会跳过公开的函数并生成如下内容:

    // CODEGEN:忽略命名空间'urn:t3'中的操作绑定'create_contact'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:忽略命名空间'urn:t3'中的操作绑定'get_contact'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'get_domain_info'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'get_last_error_code'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'get_last_error_msg'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:忽略命名空间'urn:t3'中的操作绑定'get_NSSET'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'get_owner_mail'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:忽略命名空间'urn:t3'中的操作绑定'send_auth_info'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:忽略命名空间'urn:t3'中的操作绑定'transfer_domain'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'request_sendmail'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:忽略来自命名空间'urn:t3'的操作绑定'login'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'register_domain'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:忽略命名空间'urn:t3'中的操作绑定'register_domain_with_admin_contacts'。 use = encoded消息中的每个消息部分都必须指定一个类型。 // CODEGEN:命名空间'urn:t3'中的操作绑定'renew_domain'被忽略。 use = encoded消息中的每个消息部分都必须指定一个类型。

  2. 编辑:

    我为我的手写代码尝试了这段代码。

    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("foo@mydomain.com", "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();
                 }  
            }
    

    但是当我尝试得到回应时,它会返回

      

    远程服务器返回错误:(500)内部服务器错误。

3 个答案:

答案 0 :(得分:6)

如上所述 - 您必须为此Web服务代理您的“代理”。

手动进行Web服务调用的一个示例 - 您可能需要调整一些方法。

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

我建议创建可用于生成对象的xsd(使用xsd.exe),然后您可以序列化/反序列化对实际对象的响应和请求。

编辑: 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();
        }

史蒂夫参考

调用一个看起来像:

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

响应:

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

答案 1 :(得分:1)

“webservice”是一个非常通用的术语。某些类型的Web服务可能实现WSDL - 但它不是必需的。 IIRC需要一个SOAP接口来提供WSDL,而nuSOAP和PHP SOAP扩展都支持WSDL。所以看起来远程端没有正确实现。

答案 2 :(得分:0)

编辑: 以前我收到了500内部服务器错误,因为我的soap字符串格式不正确。我分析了从Web服务返回的xml,并通过查看xml构建了我的soap字符串消息。 最后,我在 Dan ^&amp;的帮助下解决了这个问题。对互联网的一些研究。谢谢Dan。

  

我遇到了500服务器错误。现在我   能够得到登录的回复   至少失败......

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\">Support@foo.net</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("Support@foo.net", "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;
        }

现在接下来的问题是传递正确的凭据并处理响应以执行其他操作......

不过,这是回复....

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

编辑: 值false为Ok,因为我发送了错误的凭据。我以类似的方式调用Web服务的其他功能,并能够调用Web服务的所有功能并检索相应的返回值,然后执行其他处理。

感谢所有帮助解决问题的人。

此致