Подтвердить что ты не робот

Функция WSDL PHP возвращает значение null, тогда как другая функция возвращает ожидаемый результат

Резюме

Здесь я перечислил все шаги, которые я предпринял для решения этой проблемы как ссылки для других.

1. PHP, достаточно глупо, "слушает" входное сообщение функции, чтобы определить, какую функцию она должна использовать. Поэтому дайте каждой из ваших функций другое входное сообщение, даже если оно использует тот же тип или элемент. Вы можете подумать, что это довольно определенная работа для вас, но это можно сделать следующим образом:

<xsi:complexType name="UserCredentials">
<xsi:attribute name="customerID" type="xsi:int"/>
</xsi:complexType>

<xsi:element name="UserCredentials" type="types:UserCredentials"/>
<xsi:element name="UserCredentials1" type="types:UserCredentials"/>

<wsdl:message name="getCustomerCredentials">
 <wsdl:part name="body" element="types:UserCredentials"/>
</wsdl:message>
<wsdl:message name="getCustomerCredentials1">
<wsdl:part name="body" element="types:UserCredentials1"/>
</wsdl:message>

Затем Visual Studio ныла, я потратил пару дней на то, чтобы понять эту тупо идиотскую простую вещь, просто скажите программе, что вы только что установили свойство объектов:

 UserCredentials.customerID = User.CustomerID;
 UserCredentials.customerIDSpecified = true;

И что это. Я не могу в это поверить. Я провожу 1,5 недели, решение - два шага, пожалуйста, дайте этому парню, который ответил ниже некоторых голосов.

Обновление

Мой входной объект НЕ запускается в XML.

//Fix:

Вы должны сообщить программе, что свойство установлено так:

UserCredentials.customerID = User.CustomerID;
UserCredentials.customerIDSpecified = true;

Fiddler показывает это:

Ввод

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<UserCredentials2 xmlns="http://5.157.80.21/servicehandler/wsdl_service.wsdl"/>   
</s:Body>
</s:Envelope>

Выход

<?xml version="1.0" encoding="UTF-8"?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="types">
<SOAP-ENV:Body>
<ns1:PersoonArray/>
</SOAP-ENV:Body>
</SOAP-ENV:E‌​nvelope>

Что-то не так с этим кодом?

    public static List<Klant> GetAllPersonen()
    {
        List<Klant> list = new List<Klant>();

        WeGotchaService.Persoon[] servicePersonen = dpc.getAllPersoonData(UserCredentials);

        foreach (WeGotchaService.Persoon p in servicePersonen)
        {
            Klant k = new Klant(p);
            list.Add(k);
        }

        return list;
    }

Обновить комментарий

<xsi:complexType name="UserCredentials">
        <xsi:attribute name="customerID" type="xsi:int"/>       
    </xsi:complexType>
        <xsi:element name="UserCredentials" type="tns:UserCredentials" />
        <xsi:element name="UserCredentials2" type="tns:UserCredentials"/>

 <wsdl:message name="getCustomerCredentials">
    <wsdl:part name="body" element="ns:UserCredentials"/>
</wsdl:message>
<wsdl:message name="getCustomerCredentials2">
    <wsdl:part name="body" element="ns:UserCredentials2"/>
</wsdl:message>

    <wsdl:operation name="getAllLessenData">
        <wsdl:input message="ns:getCustomerCredentials"/>
        <wsdl:output message="ns2:LessenList"/>
    </wsdl:operation>
    <wsdl:operation name="getAllPersoonData">
        <wsdl:input message="ns:getCustomerCredentials2"/>
        <wsdl:output message="ns3:PersoonList"/>
    </wsdl:operation>

Это похоже на работу, за исключением того, что теперь он возвращает массив count = 0 в VS10

Другое обновление

В комментариях кто-то разместил ссылку в отчет об ошибке с PHP. Второй последний комментатор утверждал, что он работал над той же самой проблемой, что и я, разместив все защитные сообщения в других файлах и включив их в этот основной документ WSDL. Я пробовал это, но это не сработало, ничего не изменилось.

UPDATE:

Итак, я изменил порядок функций, определенных в методе привязки, и выяснил следующее: работает только первая функция, определенная в области привязки, поэтому в этом случае работает только моя getAllLessenData, потому что я поставил ее выше всех другие. Кто-нибудь видит ошибку?

 <wsdl:binding name="DataBinding" type="tns:DataPort">
    <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getAllLessenData">
        <soap:operation soapAction="" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getAllPersoonData">
        <soap:operation soapAction="" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getAllBetalingData">
        <soap:operation soapAction="" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getPersoonLessenData">
        <soap:operation soapAction="" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getPersoonBetalingenData">
        <soap:operation soapAction="" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
</wsdl:binding>

конец обновления

У меня небольшая проблема с WSLD (снова)

my getAllLessenData (и другие функции) возвращает NULL, а одна функция (getAllPersoonData) возвращает ожидаемое.

Ограничения массива WSDL:

<xsi:element name="PersoonArray">
            <xsi:complexType>
                <xsi:sequence>
                    <xsi:element name="Persoon" type="tns:Persoon" maxOccurs="unbounded"/>
                </xsi:sequence>
            </xsi:complexType>
        </xsi:element>
        <xsi:element name="LessenArray">
            <xsi:complexType>
                <xsi:sequence>
                    <xsi:element name="Les" type="tns:Les" maxOccurs="unbounded"/>
                </xsi:sequence>
            </xsi:complexType>
        </xsi:element>

WSDL complexType defenitions:

        <xsi:complexType name="Les">
            <xsi:attribute name="ID" type="xsi:int"/>
            // lots of stuff //
            <xsi:attribute name="Definitief" type="xsi:boolean"/>
        </xsi:complexType>
        <xsi:complexType name="Persoon">
            <xsi:attribute name="ID" type="xsi:int"/>
            <// lots of stuff //
            <xsi:attribute name="Laatste_keer_bewerkt" type="xsi:dateTime"/>
        </xsi:complexType>

Понижение сообщений WSDL:

<wsdl:message name="getCustomerID">
    <wsdl:part name="CustomerID" type="xs:int"/>
</wsdl:message>
<wsdl:message name="PersoonList">
    <wsdl:part name="PersoonList" element="tns:PersoonArray"/>
</wsdl:message>
    <wsdl:message name="LessenList">
    <wsdl:part name="LessenList" element="tns:LessenArray"/>
</wsdl:message>

Уязвимость WSDL portType

 <wsdl:operation name="getAllPersoonData">
        <wsdl:input message="tns:getCustomerID"/>
        <wsdl:output message="tns:PersoonList"/>
    </wsdl:operation>
    <wsdl:operation name="getAllLessenData">
        <wsdl:input message="tns:getCustomerID"/>
        <wsdl:output message="tns:LessenList"/>
    </wsdl:operation>

Защита привязки WSDL

        <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getAllPersoonData">
        <soap:operation soapAction="http://localhost/weGotcha/servicehandler/servicehandler.php" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>
    <wsdl:operation name="getAllLessenData">
        <soap:operation soapAction="http://localhost/weGotcha/servicehandler/servicehandler.php" style="document"/>
        <wsdl:input>
            <soap:body use="literal"/>
        </wsdl:input>
        <wsdl:output>
            <soap:body use="literal"/>
        </wsdl:output>
    </wsdl:operation>

Дефекты функций PHP:

function getAllPersoonData($customer_ID)
{
   connectToDB();
//////////// yes I use mysqli now /////////////
   $sql = "SELECT * FROM personen WHERE Customer_ID='". $customer_ID ."'";

   $sql = mysql_query($sql) or die(mysql_error());
   $result = array();
   while($row = mysql_fetch_array($sql))
   {
  $row["Kosten_totaal"] = mysql_fetch_array(mysql_query("SELECT SUM(Kosten) FROM lessen WHERE Persoon_ID='". $row["ID"] ."'"))[0];
    $row["Totaal_betaald"] = mysql_fetch_array(mysql_query("SELECT SUM(Bedrag) FROM betalingen WHERE Persoon_ID='". $row["ID"] ."'"))[0];
    $lkbDatum = strtotime($row["Laatste_keer_bewerkt"]);
  $row["Laatste_keer_bewerkt"] = date("Y-m-d", $lkbDatum) . "T". date("H:i:s", $lkbDatum);
  $result[] = $row;             
}
mysql_close();

   return $result;
 }


 function getAllLessenData($customer_ID)
 {
$sql = "SELECT * FROM lessen WHERE Customer_ID='". $customer_ID ."'";
//////////// yes I use mysqli now /////////////
connectToDB();

    $sql = mysql_query($sql) or die(mysql_error());
$result = array();
while($row = mysql_fetch_array($sql))
{
  $result[] = $row;
}
mysql_close();

    return $result;
 }

 $server = new SoapServer("wsdl_service.wsdl");
 $server->AddFunction("getAllPersoonData");
 $server->AddFunction("getAllBetalingData");
 $server->AddFunction("getPersoonBetalingData");
 $server->AddFunction("getAllLessenData");
 $server->AddFunction("getPersoonLessenData");
 $server->handle();

test.php

$client = new SoapClient("http://localhost/weGotcha/servicehandler/wsdl_service.wsdl", array("trace" => 1));

var_dump($client->__getFunctions());

var_dump($client->getAllLessenData(1));

var_dump($client->__getLastRequest());
var_dump($client->__getLastResponse());

который возвращает:

array (size=5)
  0 => string 'PersoonArray getAllPersoonData(int $CustomerID)' (length=47)
  1 => string 'LessenArray getAllLessenData(int $CustomerID)' (length=45)
  2 => string 'BetalingenArray getAllBetalingData(int $CustomerID)' (length=51)
  3 => string 'LessenArray getPersoonLessenData(int $getCustomerID, int $getPersoonID)' (length=71)
  4 => string 'BetalingenArray getPersoonBetalingenData(int $getCustomerID, int $getPersoonID)' (length=79)
null
string '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><CustomerID>1</CustomerID></SOAP-ENV:Body></SOAP-ENV:Envelope>
' (length=195)
string '<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"  xmlns:ns1="http://localhost/weGotcha/servicehandler/wsdl_service.wsdl"><SOAP-ENV:Body> <ns1:PersoonArray><ns1:Persoon ID="1" Voornaam="xxxx" Achternaam="xxxx"  Adres="xxxx" Postcode="xxxx" Woonplaats="xxxx"  Email_adres="xxxx" Telefoonnummer="xxxx" Geboortedatum="0001-01-01" CBR_kandidaatnummer="12381233" Rijbewijs="2" Theorie_behaald="false" Theorie_po'... (length=3096)

В моей базе данных есть строки и вызов getAllLessenData (1) непосредственно из моего сервисаhandler.php возвращает ожидаемые результаты. однако в моем test.php он просто возвращает NULL, а getLastResponse возвращает результаты getAllPersoonData (1).

Оба обезащиты выглядят одинаково для меня, черт возьми, я скопировал большую часть его. Я попытался изменить пространства имен и т.д. Google. но это не сработало. Любые идеи?

Если вам нужна дополнительная информация, ответьте.

4b9b3361

Ответ 1

РЕДАКТИРОВАТЬ 1: Это может также иметь отношение к тому, что getAllPersoonData и getAllLessenData имеют одну и ту же входную подпись, а это означает, что для веб-служб стиля документа с буквальным именем конечная точка не сможет отличить то, что вид запроса, который вы на самом деле делаете. Попробуйте передать два разных имени элемента.

EDIT 2: Кроме того, при предоставлении этих сообщений разные подписи позволят вам поместить getPersoonID в определение типа, чтобы у вас была только одна часть сообщения. Прямо сейчас, если вы посмотрите в Customer.wsdl, у вас есть:

<wsdl:message name="getPersoonIDCustomerID">
    <wsdl:part name="body" element="ns:UserCredentials"/>
    <wsdl:part name="getPersoonID" type="xs:int"/>
</wsdl:message>

У вас не должно быть более одной части сообщения документа-литера.

РЕДАКТИРОВАТЬ 3: Если вы не хотите определять новый элемент для каждой функции, которая у вас есть, вам придется переключиться на литерал RPC, который завершает запрос в wsdl:operation. Если это исправит все, кроме .NET, тогда вы можете попробовать опубликовать fooobar.com/info/439703/... сообщение о том, чтобы уговорить .NET на чтение RPC-литеральных веб-сервисов.