Get WCF to recognise incoming SOAP request - wcf

I'm trying to write a C# app to receive eBay notifications which are sent as SOAP over HTTP. I am receiving the notifications OK but I can't get them passed to my WCF service. What do I need to do on the WCF service configuration to allow the incoming SOAP request to be recognised? I'm using a webHttpBinding with the WCF service.
The SOAP request is:
POST /paypal/ebaynotification.svc HTTP/1.0
Host: myserver.com
Content-Type: text/xml;charset=utf-8
SOAPAction: "http://developer.ebay.com/notification/ItemListed"
Content-Length: 6610
X-Original-Client: 10.71.29.83
Via: 1.0 sjcproxy10b:8081 (squid)
Cache-Control: max-age=86400
Connection: keep-alive
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<ebl:RequesterCredentials soapenv:mustUnderstand="0" xmlns:ns="urn:ebay:apis:eBLBaseComponents" xmlns:ebl="urn:ebay:apis:eBLBaseComponents">
<ebl:NotificationSignature xmlns:ebl="urn:ebay:apis:eBLBaseComponents">RnvpyFAXc9Duo0W+/Mk68g==</ebl:NotificationSignature>
</ebl:RequesterCredentials>
</soapenv:Header>
<soapenv:Body>
....
</soapenv:Body>
</soapenv:Envelope>
My WCF service interface is:
[ServiceContract(Namespace="http://developer.ebay.com/notification")]
public interface Iebaynotification
{
[OperationContract]
void ItemListed(ItemType item);
}

You need something to "catch" that incoming SOAP request and spin up the WCF class to handle it.
You can either have a self-hosted WCF service (e.g. inside a Windows NT Service) listening on a given endpoint URL, or you can have a message-based activation, like IIS/WAS that will catch an incoming message and pass it to WCF for handling.
So basically, you need to implement that service contract in a WCF service class, and then you need to host / deploy that WCF service in such a way that the incoming message will be handled by it.
But most importantly: since it's a SOAP message, you cannot use webHttpBinding which is the binding used for WCF REST services. You will need to use something like basicHttpBinding or wsHttpBinding.

If eBay exposes a SOAP endpoint, I would guess that they've have a publicized a WSDL document describing the callback service. You can use the svcutil.exe command line tool to generate a correct WCF contract(s) / C# interface that you need to implement in your service implementation to handle the SOAP message you're describing. See eBay's API documentation...

Related

Consuming wsdl soap service with servicestack

I have been trying to consume wsdl soap service with asp.net C# mvc5 application. The original service is written in php which should ideally not matter but I have not been able to make this work. I have just learnt that servicestack is an alternative that works well with mvc architecture. I am looking for pointers on how to consume wsdl soap service with servicestack any help on this will be appreciated. I am happy to buy books that will guide me on how to any of these two methods will work with my mvc application
ServiceStack allows your .NET Services to be exposed via SOAP endpoints by automatically generating WSDL's and XSD's for SOAP Compatible Services which can be consumed with either the generated client proxy created with VS .NET's Add Service Reference or with ServiceStack's .NET Soap11ServiceClient and Soap12ServiceClient.
But ServiceStack doesn't provide a general purpose SOAP client for consuming any 3rd party SOAP Services. SOAP's an unnecessarily complex and brittle format where your best option is to ask the developers of the PHP SOAP Service if they can recommend any .NET SOAP clients since it's unlikely any independent SOAP client implementations will be interoperable without issues unless they've been tested and verified as compatible.
Failing that the most reliable option is to treat the SOAP XML as a string where you construct a raw SOAP Request and POST it to the remote endpoint, e.g SOAP 1.1 Request:
var soapRequest = #"<?xml version="1.0" encoding="utf-8"?>
<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>"
+ requestXml
+ "</soap:Body></soap:Envelope>";
Example POST'ing XML using HTTP Utils:
var soapResponseXml = soapEndpointUrl.PostXmlToUrl(soapRequest,
httpReq => httpReq.Headers["SOAPAction"] = requestName);
Then parse the SOAP Response with WCF's Message.CreateMessage(), if even WCF generic Message doesn't support the SOAP Response you can try to parse it dynamically as XML using something like XLINQ's XDocument.

Where is SoapAction configured in WCF Client?

I need my wcf client to communicate with the service with a blank SoapAction because the service is configured to dispatch the operation by body of the soap message. And the operation contract is decorated as below so it will not require soap action. I guess WCF sends a soapaction by default. Is there any option in wcf client to send a blank soapaction? Thanks for any help!
[OperationContract(Action="")]
use the same OperationContract attribute on your client code, i.e. reference.cs. More details here.

How to get the soap or http request object from a wcf class

From a wcf4 service need to access to the underlying http request,including it's soap message, how can I do that from code?, I know I can use fiddler, etc, but need to do it programatically.
Look at Message Inspectors.

How do I consume a WCF Soap 1.2 Web Service using a CXF Web Service Client?

Does anyone know the trick to calling a WCF (Soap 1.2) web service from CXF?
I've been trying to get a basic hello world client working for a while now and I've had no luck.
It works fine with Soap 1.1.
When I print out the SoapBinding the client is using it's using soap 1.1 even though it's a soap 1.2 service
when I set the soap binding manually to 1.2 it freezes up when you make the web service call and eventually dies with a socket timeout exception (Read timed out).
public static void main(String[] args) {
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(ITest.class);
factory.setAddress("http://localhost/Test/test.svc");
final Soap12 soap12 = Soap12.getInstance();
BindingConfiguration config = new BindingConfiguration() {
#Override
public String getBindingId() {
return soap12.getBindingId();
}
};
factory.setBindingConfig(config);
factory.setBindingId(soap12.getBindingId());
ITest service = (ITest) factory.create();
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(service);
client.getRequestContext().put("ContentType", "text/xml; charset=utf-8");
SoapBinding binding = (SoapBinding) client.getEndpoint().getBinding();
System.out.println("[" + binding.getSoapVersion() + "]");
System.out.println(service.test("World"));
}
This is the soap request that gets sent to the WCF Service.
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<Test xmlns="http://tempuri.org/" xmlns:ns2="http://schemas.microsoft.com/2003/10/Serialization/">
<s>World</s>
</Test>
</soap:Body>
</soap:Envelope>
I think your major issue with the communication between the WCF and CXF is the lack of ws-addressing headers present on the request. When you enable wsHttpBinding, WCF expects a client that understands ws-addressing. This is a feature of CXF, but needs to be enabled. The following code should resolve your issues:
// add the ws-addressing feature on the proxy factory.
factory.getFeatures().add(new org.apache.cxf.ws.addressing.WSAddressingFeature());
This solution works with CXF 3.x.
I actually found out CXF doesn't support calling a Soap 1.2 WCF Service that uses wsHttpBinding. I switched the WCF web service to use BasicHttpBinding and It works now.

Call WCF Using SOAP call

I want to call a WCF service using SOAP?
this is my contract:
[ServiceContract(Namespace = "http://www.MySite.com/Services/TransferFile")]
public interface ITransferFile : ICloseableAndAbortable
{
/// <summary>
/// This will send the file which is associated with this rule to all the subscribers.
/// </summary>
/// <param name="ruleId"></param>
[OperationContract]
void ByRuleId(int ruleId);
}
the binding is currently set to this, will i need to change it?
<endpoint address="" binding="wsHttpBinding" contract="FileTransfer.Wcf.ITransferFile">
so how would i call it via soap? for example using the (HttpWebRequest)WebRequest
Many thanks in advance
Change the Binding to basicHttpBinding
2 the message
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<ByRuleId xmlns="http://www.MySite.com/Services/TransferFile">
<ruleId>3</ruleId>
</ByRuleId>
</soap:Body>
</soap:Envelope>
3 the soap action
POST /FileTransferService/TransferFile.svc HTTP/1.1
SOAPAction: "http://www.MySite.com/Services/TransferFile/ITransferFile/ByRuleId"
fyi i asked for a (HttpWebRequest)WebRequest, only as a posible way, I ended up using a Web Reference and fiddler
Is there a reason you prefer WebRequest instead of generating a client proxy with svcutil.exe which takes care of all the plumbing?
There's a number of ways you can do this:
create a little WCF client for your service yourself, by using svcutil or "Add Service Reference" in a Visual Studio project
run a SOAP testing tool like SoapUI or WCFStorm against your service and create requests and call your service (and see the results)
use the WCF test client WcfTestClient.exe which is in your (Visual Studio)\Common7\IDE\Tools\bin (?? not 100% sure about the location - check and you'll find it for sure!) and which allows you to connect to a running WCF service, inspect its operations, and also call them
Marc