So I'm trying to call a webservice with PHP and SOAP, but it doesn't seem to be doing it correctly and I can't figure out why. Here is the PHP:
$client = new SoapClient($wsdl, array('trace' => 1));
print_r($client->__getFunctions());
$params->param1 = "satsys";
$params->param2 = "0A259772-983C-4EFB-834E-6184F8E9F4E7";
$params->param3 = null;
$response = $client->SetHardwareProfile($params);
var_dump($response);
echo "Last Request: ".$client->__getLastRequest();
echo "Last Response: ".$client->__getLastResponse();
And here is the Output:
Array
(
[0] => ValidateLicenseKeyResponse ValidateLicenseKey(ValidateLicenseKey $parameters)
[1] => CreateProviderResponse CreateProvider(CreateProvider $parameters)
[2] => SetHardwareProfileResponse SetHardwareProfile(SetHardwareProfile $parameters)
[3] => UpdateCurrentVersionResponse UpdateCurrentVersion(UpdateCurrentVersion $parameters)
[4] => SoftwareUpdateAvailableResponse SoftwareUpdateAvailable(SoftwareUpdateAvailable $parameters)
[5] => GetSoftwareUpdateResponse GetSoftwareUpdate(GetSoftwareUpdate $parameters)
)
object(stdClass)#3 (1) {
["SetHardwareProfileResult"]=>
bool(false)
}
And the XML:
<?xml version="1.0" encoding="UTF-8"?>
<!--Last Request:-->
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:SetHardwareProfile/>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
<!--Last Response:-->
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<SetHardwareProfileResponse xmlns="http://tempuri.org/">
<SetHardwareProfileResult>false</SetHardwareProfileResult>
</SetHardwareProfileResponse>
</s:Body>
</s:Envelope>
Now from what I have read, it's that request that's a problem, because instead of looking like that, it should look like this:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
<SOAP-ENV:Body>
<ns1:SetHardwareProfile>
<customerId xsi:type="xsd:string">satsys</customerId>
<providerGuid xsi:type="xsd:string">0A259772-983C-4EFB-834E-6184F8E9F4E7</providerGuid>
<other xsi:type="xsd:string"></other>
</ns1:SetHardwareProfile>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Here is the service contract, for good measure (written in C#):
using System;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Collections.Generic;
namespace ProviderSync
{
[ServiceContract]
public interface IProviderSync
{
[OperationContract]
bool SetHardwareProfile(String customerId, String providerGuid, List<Device> hardware);
}
}
Okay, so the problem is that with SOAP, unlike with other languages, the parameters have to have their exact names. So the above chunk of PHP code should actually read like this:
$client = new SoapClient($wsdl, array('trace' => 1));
print_r($client->__getFunctions());
$params->customerId = "satsys";
$params->providerGuid = "0A259772-983C-4EFB-834E-6184F8E9F4E7";
$params->hardware = null;
$response = $client->SetHardwareProfile($params);
var_dump($response);
echo "Last Request: ".$client->__getLastRequest();
echo "Last Response: ".$client->__getLastResponse();
Because they're declared by the service contract as:
bool SetHardwareProfile(String customerId, String providerGuid, List<Device> hardware);
I am not sure why exactly this is the case, or if this is the case in all forms of SOAP calls, but that change fixed this problem for me.
Related
I created a C # webservice through a WSDL from another webservice made in PHP. All calls work but the parameters sent in xml always arrive null.
This is my code:
[WebService(Namespace = "urn:PGSMS")]
[GeneratedCode("System.Xml", "2.0.50727.3082")]
[System.Xml.Serialization.SoapType(Namespace = "urn:PGSMS")]
[SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
[System.Web.Script.Services.ScriptService]
public class PGSMS : System.Web.Services.WebService, PGSMSPortType
{
[WebMethod]
[OperationContract(Action = "urn:PGSMS#PGSMS")]
public string envioAvulso(string token, string carteira, string msg, string fones, string data, string retorno, string dadocliente)
{
IntegraBellinati.envioAvulsoRequest envio = new IntegraBellinati.envioAvulsoRequest();
envio.token = token;
envio.msg = msg;
envio.fones = fones;
envio.carteira = carteira;
envio.data = data;
envio.dadocliente = dadocliente;
envio.retorno = retorno;
IntegraBellinati.IntegraBellinati integra = new IntegraBellinati.IntegraBellinati();
return integra.envioAvulso(envio);
}
}
[System.ServiceModel.ServiceContract(Namespace = "urn:PGSMS", ConfigurationName = "PGSMSPortType")]
public interface PGSMSPortType
{
string envioAvulso(string token, string carteira, string msg, string fones, string data, string retorno, string dadocliente);
}
The method sendsAvulso executes normally, but all methods arrive null.
This is the xml that my client is trying to post:
<?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="urn:PGSMS" xmlns:types="urn:PGSMS/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:envioAvulso>
<token xsi:type="xsd:string">xxxxxxxxxxxxxxxx</token>
<carteira xsi:type="xsd:string">12</carteira>
<msg xsi:type="xsd:string">Teste de msg</msg>
<fones xsi:type="xsd:string">41988326802</fones>
<data xsi:type="xsd:string">2017-10-09 00:00:00</data>
<retorno xsi:type="xsd:string">12</retorno>
<dadocliente xsi:type="xsd:string">12</dadocliente>
</tns:envioAvulso>
</soap:Body>
</soap:Envelope>
Using SoapUI I was able to make the post and received the correct parameters, it generated this xml.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:PGSMS">
<soapenv:Header/>
<soapenv:Body>
<urn:envioAvulso>
<urn:token>?</urn:token>
<urn:carteira>?</urn:carteira>
<urn:msg>?</urn:msg>
<urn:fones>?</urn:fones>
<urn:data>?</urn:data>
<urn:retorno>?</urn:retorno>
<urn:dadocliente>?</urn:dadocliente>
</urn:envioAvulso>
</soapenv:Body>
</soapenv:Envelope>
But my client can not change his xml. What can I be doing wrong?
Thank's
I have to implement interface that generates two different SystemFaults
Interface:
[ServiceContract]
public interface IErrorProvider
{
[OperationContract(Action = "getError")]
[FaultContractAttribute(typeof(string), Action = "getError", Name = "Error1Fault")]
[FaultContractAttribute(typeof(string), Action = "getError", Name = "Error2Fault")]
string getError(int iArg);
}
And implementation:
Code:
public class ErrorProvider : IErrorProvider
{
public getError(int iArg)
{
if(iArg == 1)
throw new FaultException<string>("Error1Fault","you asked err 1");
if(iArg == 2)
throw new FaultException<string>("Error2Fault","you asked err 2");
return "No error";
}
}
now when I call this service, with
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<getError xmlns="http://tempuri.org/">
<iArg>1</iArg>
</getError>
</Body>
</Envelope>
I get Response:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="fi-FI">you asked err 1</faultstring>
<detail>
<Error2Fault xmlns="http://tempuri.org/">Error1Fault</Error2Fault>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
It shows clearly that first throw is used. What I need to get is:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode>s:Client</faultcode>
<faultstring xml:lang="fi-FI">you asked err 1</faultstring>
<detail>
<Error1Fault xmlns="http://tempuri.org/">Error1Fault</Error1Fault>
</detail>
</s:Fault>
</s:Body>
</s:Envelope>
How to get that? And I don't have opportunity to change the other party, so somehow I need to solve this, really newbie question but I cannot find a real solution. All documents tell me to throw self made objects but I cannot understand how that's going to help as these are just error strings.
I'm trying to consume a webservice with async methods. I have used it's WSDL to create a client and calling the metod like this:
public static GetStockResponse GetResult()
{
var client = new ServiceSoapClient();
var inItems = new ArrayOfItemNo();
inItems.Add(new ItemNoRow { ItemNo = "0000001350" });
Task<GetStockResponse> task = client.GetStockAsync(inItems, "034");
task.Wait();
return task.Result;
}
In fiddler I can see the call with status 200
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body>
<GetStockRequest xmlns="http://www.unikum.se/pws"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ItemNo>
<ItemNoRow>
<ItemNo>0000001350</ItemNo>
</ItemNoRow>
</ItemNo>
<StoreID>034</StoreID>
</GetStockRequest>
And the response:
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body>
<GetStockResponse xmlns="http://www.unikum.se/pws">
<Items>
<Item>
<ItemNo>0000001350</ItemNo>
<DeliveryTimeText>4-6 veckor</DeliveryTimeText>
<DeliveryDays>42</DeliveryDays>
<Stores>
<Store>
<StoreID>034</StoreID>
<NotInERP>N</NotInERP>
<InStockQty>2</InStockQty>
<InShowRoom>N</InShowRoom>
</Store>
</Stores>
</Item>
</Items>
</GetStockResponse>
But the result of the task (task.Result) is empty. It is a GetStockResponse but all values is null.
Why? Everything seems correct or doesn't it?
Well, some more testing with some other methods provided by the service owner clearly indicated that they did not follow the response structure defined in their own WSDL. I could see that in a simpler test where they partially followed the WSDL structure I got correct values back on those specific properties but not on those that differed. So now I could more clearly point to the error and return with "Please fix this, or else" response to the service provider.
I'm adding a property to my model with an enum.
public class ChildCareCentreEntryReservation : BasketItem, ILockableBasketItem
{
....
[DataMember]
public ChildCareCentreEntryReservationStatusTypes ChildCareCentreEntryReservationStatusType { get; set; }
}
[DataContract(Namespace = Constants.Namespace)]
public enum ChildCareCentreEntryReservationStatusTypes
{
[EnumMember]
VoorlopigIngeschreven = 0,
[EnumMember]
DefinitiefIngeschreven = 1,
[EnumMember]
Geannuleerd = 2
}
In my form I Create a ChildCareCentreEntryReservation object:
var reservation = new ChildCareCentreEntryReservation();
reservation.ChildCareEntryPeriodId = _entryPeriod.Id;
reservation.ChildCareCentreId = _centre.Id;
reservation.PersonId = _person.Id;
reservation.Comment = txtComment.Text;
reservation.ChildCareCentreEntryReservationStatusType = (ChildCareCentreEntryReservationStatusTypes)cboStatusName.SelectedIndex;
I add the ChildCareCentreEntryReservation object to a list:
var basketItems = new List<BasketItem> { reservation };
Then I send an array to the service by calling the function LockBasketItems:
LockBasketResult lockBasketResult = Service.LockBasketItems(basketItems.ToArray(), Context);
Everything builds and works correctly but my service doesn't receive my last added property.
Fiddler inspectors result (client request to service):
<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">
<BasketItems xmlns="http://www./">
<BasketItem xsi:type="ChildCareCentreEntryReservation">
<RuleNamesToIgnore xsi:nil="true"/>
<ChildCareEntryPeriodId>13ccefb3-f1e4-4f64-8fb8-b07cf30d2fca</ChildCareEntryPeriodId>
<ChildCareCentreId>8cc85f37-da5d-46c5-9bb4-d6efa8448176</ChildCareCentreId>
<PersonId>56e341bb-ac05-40dc-a39a-082ae4ff087e</PersonId>
<ChildCareCentrePeriodIds>
<guid xmlns="http://schemas.microsoft.com/2003/10/Serialization/Arrays">61c43967-8781-4d83-a117-963c5734491f</guid>
</ChildCareCentrePeriodIds>
<LockTicket xsi:nil="true"/>
<Comment/>
<PeriodOptions xsi:nil="true"/>
</BasketItem>
</BasketItems>
<Context xmlns="http://www./">
<Language>NL</Language>
<ShopId>00000000-0000-0000-0000-000000000550</ShopId>
<SessionId>de824345-14f3-44c7-99fd-f9a073e9b51b</SessionId>
</Context>
Fiddler inspectors result (service response to client):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<ActivityId CorrelationId="d1daee11-20e2-4e98-8774-9bffe4e2e4f3" xmlns="http://schemas.microsoft.com/2004/09/ServiceModel/Diagnostics">728e68a9-17ff-44a0-b4ad-f455f403be5e</ActivityId>
</s:Header>
<s:Body>
<LockBasketResult xmlns="http://www./" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<BasketItems>
<BasketItem i:type="ChildCareCentreEntryReservation">
<DivisionId>00000000-0000-0000-0000-000000000000</DivisionId>
<Id>00000000-0000-0000-0000-000000000000</Id>
<Quantity>1</Quantity>
<RuleNamesToIgnore xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays"/>
<UnitPrice>0</UnitPrice>
<ChildCareEntryPeriodId>13ccefb3-f1e4-4f64-8fb8-b07cf30d2fca</ChildCareEntryPeriodId>
<ChildCareCentreId>8cc85f37-da5d-46c5-9bb4-d6efa8448176</ChildCareCentreId>
<PersonId>56e341bb-ac05-40dc-a39a-082ae4ff087e</PersonId>
<ChildCareCentrePeriodIds xmlns:a="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<a:guid>61c43967-8781-4d83-a117-963c5734491f</a:guid>
</ChildCareCentrePeriodIds>
<LockTicket i:type="ChildCareCentreEntryReservationLockTicket">
<ExpirationTime>2013-10-08T17:27:06</ExpirationTime>
<Id>13a984f8-5d97-4f87-aa52-7523849cc6f5</Id>
</LockTicket>
<Comment/>
<PeriodOptions xmlns:a="http://schemas.datacontract.org/"/>
<ChildCareCentreEntryReservationStatusType>VoorlopigIngeschreven</ChildCareCentreEntryReservationStatusType>
</BasketItem>
</BasketItems>
<IsLocked>true</IsLocked>
<ValidationResult i:nil="true"/>
</LockBasketResult>
In my Reference.cs i'm seeing the property is correctly added.
Any idea what i am missing?
I'm using ASP.NET
Solution
I had to set ChildCareCentreEntryReservationStatusTypeSpecified to true
reservation.ChildCareCentreEntryReservationStatusTypeSpecified = true;
Solved
I had to set ChildCareCentreEntryReservationStatusTypeSpecified to true
reservation.ChildCareCentreEntryReservationStatusTypeSpecified = true;
Here is the XML response:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="somehttp..">
<soap:Body>
<get4GAddressResponse xmlns="http://somelink/">
<get4GCAddressResult>
<located>true</located>
<matchStatus>S</matchStatus>
<errorCode>0</errorCode>
<message>Single Address Match</message>
<addressList>
<anyType xsi:type="Address">
<street>4301 some St</street>
<city>ABC</city>
<state>TX</state>
<zip>78751</zip>
<longitude>-97.700000</longitude>
<latitude>30.308000</latitude>
<coverageTypes>
<anyType xsi:type="NetworkCoverage">
<type>4G</type>
<isCovered>false</isCovered>
</anyType>
</coverageTypes>
</anyType>
</addressList>
</get4GAddressResult>
</get4GAddressResponse>
</soap:Body>
</soap:Envelope>"
I am trying to get the values from XML element: 'isCovered'
I am able to retrieve the values from
<located>true</located>
<matchStatus>S</matchStatus>
<errorCode>0</errorCode>
<message>Single Address Match</message>
But I need value for IsCovered.
C# code:
Location result = new TestWebService.Location();
result = get4GAddress(street, city, state, zip);
if (result != null)
{
if (result.errorCode.Equals("0"))
{
locationresult = new LocationResponse();
locationresult.located = result.located;
locationresult.addressList = result.addressList;
locationresult.matchStatus = result.matchStatus;
locationresult.message = result.message;
}
}
You can use the SoapFormatter to deserialize your response stream.