
soap_server.php
<?php class math_test {
public function add($a, $b) { return $a + $b; }
public function sub($a, $b) { return $a - $b; }
public function div($a, $b) { if($b == 0) { throw new SoapFault(-1, "Cannot divide by zero!"); } return $a / $b; } }
ini_set("soap.wsdl_cache_enabled", "0"); // disabling WSDL cache $server = new SoapServer('math.wsdl', array('soap_version' => SOAP_1_2)); $server->setClass("math_test"); $server->handle(); ?> |
math.wsdl
<?xml version='1.0' encoding='UTF-8'?>
<definitions name="math" targetNamespace="urn:math" xmlns:typens="urn:math" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <message name="add"> <part name="a" type="xsd:integer"/> <part name="b" type="xsd:integer"/> </message> <message name="addResponse"> <part name="addReturn" type="xsd:integer"/> </message> <message name="div"> <part name="a" type="xsd:integer"/> <part name="b" type="xsd:integer"/> </message> <message name="divResponse"> <part name="divReturn" type="xsd:double"/> </message> <message name="sub"> <part name="a" type="xsd:integer"/> <part name="b" type="xsd:integer"/> </message> <message name="subResponse"> <part name="subReturn" type="xsd:integer"/> </message> <portType name="servicePortType"> <operation name="add"> <documentation> Add two integers together </documentation> <input message="typens:add"/> <output message="typens:addResponse"/> </operation> <operation name="div"> <documentation> Div two integers from each other </documentation> <input message="typens:div"/> <output message="typens:divResponse"/> </operation> <operation name="sub"> <documentation> Subtract two integers from each other </documentation> <input message="typens:sub"/> <output message="typens:subResponse"/> </operation> </portType> <binding name="serviceBinding" type="typens:servicePortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <operation name="add"> <soap:operation soapAction="urn:serviceAction"/> <input> <soap:body namespace="urn:math" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body namespace="urn:math" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="div"> <soap:operation soapAction="urn:serviceAction"/> <input> <soap:body namespace="urn:math" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body namespace="urn:math" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> <operation name="sub"> <soap:operation soapAction="urn:serviceAction"/> <input> <soap:body namespace="urn:math" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </input> <output> <soap:body namespace="urn:math" use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/> </output> </operation> </binding> <service name="mathService"> <port name="servicePort" binding="typens:serviceBinding"> <soap:address location="http://192.168.1.134/soap_server.php"/> </port> </service> </definitions> |
soap_client.php
<?php ini_set ("soap.wsdl_cache_enabled", "0"); //$client = new SoapClient("math.wsdl"); $client = new SoapClient('http://192.168.1.134/soap_server.php?wsdl'); try { $us = $client -> sub(8, 2); print "The answer is: $us"; } catch(SoapFault $e) { print "Sorry an error was caught executing your request: {$e->getMessage()}"; } ?> |
test3.aspx
關鍵在於取用php soap所定義的Namespace、service name及function name,與取用.NET Web Service的Namespace、Class、Method同理。
<%@ Page Language="C#" Debug="true"%> <%@ Import Namespace="System" %> <%@ Import Namespace="System.Web" %> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Web.Services" %> <%@ Import Namespace="System.Net" %> <%@ Import Namespace="System.IO" %> <%@ Import Namespace="System.Web.Services.Description" %> <%@ Import Namespace="System.CodeDom" %> <%@ Import Namespace="Microsoft.CSharp" %> <%@ Import Namespace="System.CodeDom.Compiler" %>
<script runat="server"> protected void Page_Load(object sender, EventArgs e) { string url = "http://192.168.1.134/soap_server.php"; string @namespace = "abcdef"; //欲呼叫的WebService的命名空間,隨便輸入 string classname = "mathService"; //欲呼叫的WebService的類名,math.wsdl所定義的service name,上面標黃底紅字的區塊 string methodname = "div"; //欲呼叫的WebService的方法名,soap_server.php所定義的function name,上面標黃底紅字的區塊
string[] args = new string[2]; //參數列表 args[0] = "8"; //傳入計算的參數值 args[1] = "2"; //傳入計算的參數值 object objReturn = InvokeWebservice(url, @namespace, classname, methodname, args); Label99.Text = "PHP SOAP Web Service計算答案 = " + objReturn.ToString(); }
public object InvokeWebservice(string pUrl, string @pNamespace, string pClassname, string pMethodname, object[] pArgs) { WebClient tWebClient = new WebClient(); //讀取WSDL檔,確認Web Service描述內容 Stream tStream = tWebClient.OpenRead(pUrl + "?wsdl"); ServiceDescription tServiceDesp = ServiceDescription.Read(tStream); //將讀取到的WSDL檔描述import近來 ServiceDescriptionImporter tServiceDespImport = new ServiceDescriptionImporter(); tServiceDespImport.AddServiceDescription(tServiceDesp, "", ""); CodeNamespace tCodeNamespace = new CodeNamespace(@pNamespace); //指定要編譯程式 CodeCompileUnit tCodeComUnit = new CodeCompileUnit(); tCodeComUnit.Namespaces.Add(tCodeNamespace); tServiceDespImport.Import(tCodeNamespace, tCodeComUnit);
//以C#的Compiler來進行編譯 CSharpCodeProvider tCSProvider = new CSharpCodeProvider(); ICodeCompiler tCodeCom = tCSProvider.CreateCompiler();
//設定編譯參數 System.CodeDom.Compiler.CompilerParameters tComPara = new System.CodeDom.Compiler.CompilerParameters(); tComPara.GenerateExecutable = false; tComPara.GenerateInMemory = true;
//取得編譯結果 System.CodeDom.Compiler.CompilerResults tComResult = tCodeCom.CompileAssemblyFromDom(tComPara, tCodeComUnit);
//如果編譯有錯誤的話,將錯誤訊息丟出 if (true == tComResult.Errors.HasErrors) { System.Text.StringBuilder tStr = new System.Text.StringBuilder(); foreach (System.CodeDom.Compiler.CompilerError tComError in tComResult.Errors) { tStr.Append(tComError.ToString()); tStr.Append(System.Environment.NewLine); } throw new Exception(tStr.ToString()); }
//取得編譯後產出的Assembly System.Reflection.Assembly tAssembly = tComResult.CompiledAssembly; Type tType = tAssembly.GetType(@pNamespace + "." + pClassname, true, true); object tTypeInstance = Activator.CreateInstance(tType); //若WS有overload的話,需明確指定參數內容 Type[] tArgsType = null; if (pArgs == null) { tArgsType = new Type[0]; } else { int tArgsLength = pArgs.Length; tArgsType = new Type[tArgsLength]; for (int i = 0; i < tArgsLength; i++) { tArgsType[i] = pArgs[i].GetType(); } }
//若沒有overload的話,第二個參數便不需要,這邊要注意的是WsiProfiles.BasicProfile1_1本身不支援Web Service overload,因此需要改成不遵守WsiProfiles.BasicProfile1_1協議 System.Reflection.MethodInfo tInvokeMethod = tType.GetMethod(pMethodname, tArgsType); //實際invoke該method return tInvokeMethod.Invoke(tTypeInstance, pArgs); } </script>
<html> <head runat="server"> </head> <body> <form id="form1" runat="server">
<asp:Label ID="Label99" runat="server" Text="" />
</form> </body> </html> |
