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>

 
結果畫面:
 
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 adamschen9921 的頭像
    adamschen9921

    昶達的部落格

    adamschen9921 發表在 痞客邦 留言(1) 人氣()