WCF service, gSoap 415 error

 ( makgab | 2015. április 22., szerda - 10:32 )

Üdv!

Egy WCF service-t (M$ WFC) próbálok elérni gsoap-al (gsoap-2.8.16-8.fc21.x86_64). A generálás megvolt:
~# wsdl2h -o myservice.h http://< wsdl.url >
~# soapcpp2 -j myservice.h

A c++ kódban 415-ös hibakódot kapok:

if ( s.GetServer(tr) == SOAP_OK )
std::cout << "Result: " << tr->GetServerResult << std::endl;
else
s.soap_stream_fault(std::cerr);

A 415-ös hibakód:
"HTTP Error"
Detail: HTTP/1.1 415 Cannot process the message because the content type 'application/soap+xml; charset=utf-8;
action="http://tempuri.org/IWEBDACOService/GetServerTime"' was not the expected type 'text/xml; charset=utf-8'

Azaz "application/soap+xml" formátumot kap a WCF server a "text/xml" helyett. Ez azt jelentené, hogy soap 1.2 helyett soap 1.1 kellene használnom.

Hogy tudom ezt a problémát javítani?
A fenti linken említett .nsmap and C++ Proxy header file módosítása nem hozott javulást.

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Talán szerver oldalon:
basicHttpBinding -> wsHttpBinding?

A generalt gsoaphoz nem ertek, de wcf oldalon be tudod allitani a messageencodingot, asszem mtom az soap1.2 text pedig soap 1.1!
Szerintem a wshttpbindingnak ehhez semmi koze, a MessageEncoding -t allitsd a szerver oldalon Textre, ha ott akarsz soap1.1-t.

szepnap

A WCF soap1.2 be lett állítva, ujrageneráltam a proxy-t:
wsdl2h -o myservice.h http://soap_server.wsdl
soapcpp2 -j myservice.h

A teszt:

if ( s.GetServerTime(t, tr) == SOAP_OK )
std::cout << "Server time: " << tr->GetServerTimeResult << std::endl;
else
s.soap_stream_fault(std::cerr);

Nem egészen értem a hibát:

SOAP 1.2 fault: SOAP-ENV:Sender[wsa5:ActionMismatch]
"The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://tempuri.org/MyService/GetServerTime'. "
Detail: < a : ProblemHeaderQName> a : Action < / a : ProblemHeaderQName>

Google-on több helyen is látok hasonló problémát, de nem értem pontosan mi is ez.
Van ötlete valakinek?

A gsoap-ban a "security mode"-ot hol tudom állítani (none)? Elvileg ez segít rajta.

A gsoap-ban mivel tudom kiiratni az request XML tartalmat? Tehát azt szeretném tudni, hogy egyáltalán mit küld el a szerver felé.

Erre már válaszoltam én is.

--

A "WcfTestClient.exe" segítségével sikerült küldenem kérést a szerver felé és vissza is jött a válasz (Win7 alatt).
De Linux alól hogy tudok ezzel "WcfTestClient.exe"-vel rátapadni a service-re? Tehát a Linux gsoap kliensem reqest XML-ét hogyan tudom elkapni?

(A Linux-om virtuális gépben van a Win7-en.)

Itt ugyanez a probléma (csak PHP alatt):
http://stackoverflow.com/questions/8597825/php-soapclient-action-mismatch

Olvasd el a válaszom még egyszer. A service-ben is be tudsz kapcsolni üzenet szintű logolást, nem kell WireShark.

--

A wireshark-al megnéztem a request csomagot, amit a gsoap küld:

< SOAP-ENV : Envelope
xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope"
xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ser="http://schemas.microsoft.com/2003/10/Serialization/"
xmlns:ns2="http://schemas.datacontract.org/2004/07/ServiceWebRole"
xmlns:tempuri="http://tempuri.org/"
xmlns:chan="http://schemas.microsoft.com/ws/2005/02/duplex"
xmlns:wsa5="http://www.w3.org/2005/08/addressing">
< SOAP-ENV : Body >
< tempuri : GetServerTime >
< tempuri : inControlId >xxx-yyy-zzz< / tempuri:inControlId >
< / tempuri:GetServerTime >
< / SOAP-ENV:Body >
< / SOAP-ENV:Envelope >

Valóban nincs fejléce, így Action sincs benne.
A gsoap-ban kellene másképp küldeni a kérést?

Alap basicHttpBinding-ot használsz? Nem HTTP fejlécből hiányolja az action-t? Azt lenne jó látni, hogy mi a különbség a WcfTestClient és a gSoap által küldött kérés között.

--

Megvan, működik. :)
A wireshark segített, ill. ez.

Be kell állítani a fejlécet (header):

//...
// set header
char *ActionTime = "http://tempuri.org/MYService/GetServerTime";
// ...
wsa5__EndpointReferenceType replyTo = { Address,NULL,NULL,NULL,NULL,NULL };

s.soap_header( messageID, NULL, NULL, &replyTo, NULL, To, ActionTime, NULL );
if ( s.GetServerTime(t, tr) == SOAP_OK ) {
// ...

Köszönöm a segítséget mindenkinek!

Általánosságban: a WCF "túl okos", a legalapabb, nem autentikált, semmenyire se testre szabott basicHttpBinding-on kívül nem nagyon tudsz olyat beállítani, ami Javából és minden más platformról gond nélkül menne. A túl okos dolog nem vicc, tényleg szar ügy, hogy milyen rossz a WS-* szabványok támogatottsága egyéb helyeken.

A problémához: ami tutira viszi a WCF-et, az a WcfTestClient.exe. Indítsd el, tapadj rá a service-edre, küldj egy kérést, és ki tudod íratni vele a kérés teljes tartalmát. Aztán össze lehet hasonlítani avval, amit a buta kliens küld. Ajánlom még figyelmedbe az SvcConfigEditor.exe és SvcTraceViewer.exe cuccokat, előbbivel kényelmesen be tudsz állítani egy nagyon részletes, akár teljes üzenet szintű logolást, amit utóbbival tudsz elemezni. A hibakódozást meg a guglizást felejtsd el, ezerféleképpen tud elromlani hasonló tünetekkel. Ez a loggolás megmondja a tutit, kintről nézve csak egy fekete doboz.

--