how to select FaultContractAtribute based on Name parameter - c#

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.

Related

Overwrite WS-Adressing-Header (to and Action)

i have to access an SOAP-service with WS-Adressing. I simply imported the WSDL i got and i try to connect. But the Service is not happy with the generated WS-Adressing Headers.
My code looks like this:
var binding = new WSHttpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
var entpointAddr = new EndpointAddress("https://endpoint123/services");
using (var client = new DocumentManagementServicePortTypeClient(binding, entpointAddr))
{
client.ClientCredentials?.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.My, X509FindType.FindByThumbprint, "123123123");
try
{
var result = client.TestFunction();
Console.WriteLine(result);
}
catch (Exception exc)
{
Console.WriteLine($"Error: {exc.Message}");
}
}
This generate a Request like this:
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1"/>
<a:MessageID>urn:uuid:8123d133-c107-44cf-97be-762014fa1b83</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://endpoint123/services</a:To>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<TestFunction xmlns = "http://xmldefs...../" />
</ s:Body>
</s:Envelope>
The Server has two problems with this request:
a:To is pointed to the Endpoint
a:Action is empty
The a:To is pointed to the endpoint i set in my code-snippet. But the server expected the Endpoint defined in the WSDL (a WS:\\ uri). How could i tell WCF to use the WS:\\-Link? Or could i overwrite it manually?
I could solve the problem with the a:Action by manually adding the path in the Reference.cs, for every function i like to use, but why it is not self generated?

How to access to differents methods of webservice with SOAPUI

I try to access to my webmethods with SOAP UI but it works only for the first one and I don't undestand why.
My Webservices methods :
[SoapHeader ("AuthenticationInfo", Required=true)]
[WebMethod(EnableSession = true)]
public string HelloWorld()
{
if (!(AuthenticationInfo.Username == "test" && AuthenticationInfo.Password == "test"))
{
throw new Exception();
// I put that in the aim to get an error, I'll modify this later
}
return "OK";
}
[SoapHeader("AuthenticationInfo", Required = true)]
[WebMethod]
public string Authenticate(string MethodName)
{
if (!(AuthenticationInfo.Username == "test" && AuthenticationInfo.Password == "test")
{
throw new Exception();
}
else
{
HelloWorld();
}
return "aaaa";
}
[WebMethod]
public int Calcul(int a, int b)
{
return a+b ;
}
When I put this XML in SOAP UI :
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthHeader xmlns="http://tempuri.org/">
<Username>test</Username>
<Password>test</Password>
<key>string</key>
</AuthHeader>
</soap:Header>
<soap:Body>
<HelloWorld xmlns="http://tempuri.org/" />
</soap:Body>
</soap:Envelope
It works perfectly, I get the return of HelloWord() Method.
But if I put :
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<Calcul xmlns="http://tempuri.org/">
<a>1</a>
<b>1</b>
</Calcul>
</soap:Body>
</soap:Envelope>
It invokes again HelloWorld() method. My URL which I use in SOAP UI is :"http://localhost:62353/MyWebService.asmx", so I try a new request with the last XML at the URL "http://localhost:62353/MyWebService.asmx/Calcul" and i have an error.
Have you I Idea ? May I'm in the wrong way to use SOAP UI ?
To reply to Kosala W :
I get an UI like that where I can click on the methods. The calcul methods works only here because this methos doesn't need the SoapHeader.
Here is the response :
When you specify the URL in SOAP UI you need to add ?wsdl at the end like that : http://localhost:62353/MyWebService.asmx?wsdl Then I refresh the project in SOAP UI and all the methods appears

Async result empty but data exists in response

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.

wcf service datacontract last property not added

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;

Why is my SOAP envelope empty?

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.

Categories