Direct POST to WCF WSDL-first web service - wcf

I need some help posting some XML to a WCF service. In essence, the issue I am experiencing is a HTTP response of "400: Bad request" - as descriptive as that sounds, i'm struggling to find any answers!
First of all, the service I have built in WCF is based on an existing WSDL, originally from an IBM WebSphere web service. After some manipulation (removal of MIME attachments, downloading of some remote schemas) I managed to get svcutil to generate a service interface which for all intents and purposes seems valid.
I have implemented the interface in to my WCF service and when running the WCF test client, I can attach to the service, submit a request and receive a response no problems. So far so good!
When moving to a test application for posting XML to web services via the HttpWebRequest class I start receiving "400: Bad request" responses even though I am using the XML provided by the WCF test client.
I've used WCF tracing to dump out the messages it is receiving and there is one striking difference - all of the WCF test client messages are populating correctly and displaying their header information etc, all of the once from my SOAP test utility are showing as "Malformed". Looking in to the message tab, the manual POST messages I am sending have the body wrapped in a element:
<MessageLogTraceRecord><![CDATA[<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:57567/Service1.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.nowhere.co.uk/RequestService/RequestOperation</Action>
</s:Header>
</s:Envelope>
]]></MessageLogTraceRecord>
Whereas the WCF messages appear as:
<MessageLogTraceRecord>
<HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<Connection>Keep-Alive</Connection>
<Content-Length>185</Content-Length>
<Content-Type>text/xml; charset=utf-8</Content-Type>
<Accept-Encoding>gzip, deflate</Accept-Encoding>
<Expect>100-continue</Expect>
<Host>localhost:57567</Host>
<VsDebuggerCausalityData>uIDPo4VLDcJD5AZDjB5sdmoeakEAAAAAH/hWABuWQ0iiq47QDHh0GlelCLcEx7FLibxRvpq1tTgACQAA</VsDebuggerCausalityData>
<SOAPAction>"http://www.nowhere.co.uk/RequestService/RequestOperation"</SOAPAction>
</WebHeaders>
</HttpRequest>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:57567/Service1.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.nowhere.co.uk/RequestService/RequestOperation</Action>
</s:Header>
</s:Envelope>
</MessageLogTraceRecord>
I've tried tracing in Fiddler to no avail - I can't get the WCF test client to submit requests through the proxy it creates despite modifying it's app.config file. I have traced my SOAP request however can can see the following:
Content-Type: text/xml; charset="utf-8"
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:57567
SOAPAction: "http://www.nowhere.co.uk/RequestService/RequestOperation"
Content-Length: 459
Expect: 100-continue
Connection: Keep-Alive
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:57567/Service1.svc</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.nowhere.co.uk/RequestService/RequestOperation</Action>
</s:Header>
</s:Envelope>
As far as I can tell, the message I am sending should be ok - outside of the headers and the message content I can't see what else could be sent.
Last thing I should say is that I am by no means a WCF expert and I have had to change the specific SOAPAction value due to commercial sensitivity..
Can anyone offer any help on this rather frustrating problem?
Thanks in advance

Thanks for the Fiddler comment - I managed to get the WCF request traced and using the xml from the request seems to work! I've since tried a full message which works against the WebSphere service against the WCF client and that works too!
I think the issue was the Action header. I believe WCF only support a couple of revisions of WSA, none of which are the one this particular WSDL was using. Looking at the original requests that were failing (pulled out of the WCF Test Client front end) the addressing namespace it was using was declared as:
xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none"
Whereas the actual WCF request that goes across to the service is declared as:
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
The actual element itself was populated with the same value, just the difference in namespace:
<wsa:Action>http://www.nowhere.co.uk/RequestService/RequestOperation</wsa:Action>
So using the correct addressing version and omitting the newer, WCF compatible version appears to have fixed the problem!

Related

SOAP Request to local WCF Service results in "InvalidSecurity Error"

We've got a WCF service with BasicHttpBinding and tested it via SoapUI.
My co-worker can post the requests just fine, but on my machine I get the following error returned:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<s:Fault>
<faultcode xmlns:a="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">a:InvalidSecurity</faultcode>
<faultstring xml:lang="de-AT">The caller was not authenticated by the service.</faultstring>
</s:Fault>
</s:Body>
</s:Envelope>
I'm pretty clueless as to why it doesn't work on my machine. IIS Settings are the same, too. A typical "It works on MY machine!" problem...

Webservice is not working anymore after changed firewall hardware (Dell sonicwall)

We have built for a customer websiteB in c# asp.net. There is also another website in php which is builded by another company. This is websiteA. The enduser is try to log in on websiteA. Underwater there is a request to a webservice on websiteB with username/password as parameters. WebsiteB try to get authenticate the credentials and return a message. WebsiteA is running on some server of another company. WebsiteB is running on our server in the datacenter. This scenario was always working!
No we have changed the firewall hardware in our datacenter. We have now Dell SonicWall. In the beginning the certificates were not working of our webservice. We have fix this. When you run our webservice in the browser the certifcate is OK (there is no red background in the url).
This is the url of my webservice:
https://service.myCompany.com/PortalService.svc
I ask the other company to give me some logging or an exception from there side. They do not get an exception. They got an empty array. They have printed some logging for me after a request:
We have also enabled the logging on the webservice. This is the logging after trying to login on websiteA.
Request to webservice:
<MessageLogTraceRecord>
<HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<Connection>Keep-Alive</Connection>
<Content-Length>574</Content-Length>
<Content-Type>text/xml;charset=UTF-8</Content-Type>
<Accept>*/*</Accept>
<Authorization>Basic bWlqbnNlaF9uZXRieXRlczojbjN0Ynl0MzU=</Authorization>
<Host>service.MyCompany.com</Host>
<User-Agent>Jakarta Commons-HttpClient/3.1</User-Agent>
<SOAPAction>"http://schemas.MyCompany.com/SecurityService/SecurityService/LoginUsernamePassword"</SOAPAction>
</WebHeaders>
</HttpRequest>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:test="http://schemas.MyCompany.com/SecurityService">
<soapenv:Header>
<To soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://mycompanyapp01.dmz.mycompany.local/SecurityService.svc</To>
<Action soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://schemas.MyCompany.com/SecurityService/SecurityService/LoginUsernamePassword</Action>
</soapenv:Header>
<soapenv:Body>
<test:LoginUsernamePassword>
<test:Username><![CDATA[testuser#mycompany.com]]></test:Username>
<test:Password><![CDATA[#test!]]></test:Password>
<test:ReturnToken>true</test:ReturnToken>
<test:ReturnProfile>true</test:ReturnProfile>
<test:ReturnRoles>true</test:ReturnRoles>
</test:LoginUsernamePassword>
</soapenv:Body>
</soapenv:Envelope>
</MessageLogTraceRecord>
Response from webservice:
<MessageLogTraceRecord>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://schemas.MyCompany.com/SecurityService/SecurityService/LoginUsernamePasswordResponse</Action>
</s:Header>
<s:Body>
<LoginUsernamePasswordResponse xmlns="http://schemas.MyCompany.com/SecurityService">
<LoginUsernamePasswordResult xmlns:d4p1="http://schemas.MyCompany.com/datacontracts" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<d4p1:Token>PJ%2bNtW0Kpy%2frd945r3Q0ziQpoax%2bNIiPNXC8obx%2fl73D2MPTvwFA9TqDtHNzXPq7</d4p1:Token>
<d4p1:UserProfile>
<d4p1:DisplayNameFormal>Test</d4p1:DisplayNameFormal>
<d4p1:DisplayNameInformal>Test</d4p1:DisplayNameInformal>
<d4p1:Email>test#mycompany.com</d4p1:Email>
<d4p1:IsErkendAdviseur>false</d4p1:IsErkendAdviseur>
<d4p1:UserID>testuser#mycompany.com</d4p1:UserID>
</d4p1:UserProfile>
<d4p1:UserRoles xmlns:d5p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d5p1:string>Test Medewerker</d5p1:string>
</d4p1:UserRoles>
</LoginUsernamePasswordResult>
</LoginUsernamePasswordResponse>
</s:Body>
</s:Envelope>
</MessageLogTraceRecord>
I have also started the wcf client tool (wcfTestClient.exe). I add the webservice url (https://service.myCompany.com/PortalService.svc). I got this exception:
Error: Cannot obtain Metadata from https://service.MyCompany.com/SecurityService.svc?wsdl
If this is a Windows (R) Communication Foundation service to which you have access, please check that you have enabled metadata publishing at the specified address. For help enabling metadata publishing, please refer to the MSDN documentation at http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange
Error URI: https://service.MyCompany.com/SecurityService.svc?wsdl Metadata contains a reference that cannot be resolved: 'https://service.MyCompany.com/SecurityService.svc?wsdl'.
The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Basic realm="service.MyCompany.com"'.
The remote server returned an error: (401) Unauthorized.HTTP GET Error URI: https://service.MyCompany.com/SecurityService.svc?wsdl
The document was understood, but it could not be processed. - The WSDL document contains links that could not be resolved. - There was an error downloading 'https://myCompanyapp01.dmz.myCompany.local/SecurityService.svc?wsdl=wsdl0'. - The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel. - The remote certificate is invalid according to the validation procedure.
Why do I see the intern url in the exception while I testing the public url:
intern url: https://myCompanyapp01.dmz.myCompany.local/SecurityService.svc?wsdl
public url: https://service.MyCompany.com/SecurityService.svc?wsdl
The public url has a certificate. The intern url not. When you try the intern url you got a red background in the browser.
I think this whole problem is our firewall. I think there is some restricted option on SOAP outbound messages. Because websiteA which is doing the request dont get an exception. They get also an answer, but it is empty. So it looks like the firewall has make it empty.
What do you think of this problem?
Your WSDL is referencing/including files on the internal app server. Try using a flattened wsdl.

ReSTful web service to send and receive soap+xml

I am writing a RESTful web service and have a big trouble in getting the basic step up itself.
I could do the below:
Could create RESTful web service and send and receive the XML (not soap+xml) back to the client with webHttpBinding
Could create RESTful web service and send and receive the soap+xml using the contract as defined below:
[OperationContract]
[WebInvoke(Method = "POST",
UriTemplate = "",
BodyStyle = WebMessageBodyStyle.Bare,
RequestFormat = WebMessageFormat.Xml,
ResponseFormat = WebMessageFormat.Xml)]
XmlElement PostRequestXML(Stream xmlData);
Is the point (2) is right way to send and receive the soap+xml data?
I did a lots of search on web, but could not find better link which explains the detailed steps on creating web service to send and receive soap+xml.
I would like to know :
what is better way to design my RESTful web service to send and receive soap+xml? Can you show me operation contract definition?
which binding do I need to use? SHare if any example.
can you share me the detailed information on writing OperationContract and configuring web.config?
The request and respond should like as below.
REQUEST:
Header:
POST /EnrollmentServer/Discovery.svc HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
User-Agent: Windows Phone 8 Enrollment Client
Host: EnterpriseEnrollment.Contoso.com
Content-Length: xxx
Cache-Control: no-cache
<?xml version="1.0"?>
<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing"
xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">
http://schemas.microsoft.com/windows/management/2012/01/enrollment/IDiscoveryService/Discover
</a:Action>
<a:MessageID>urn:uuid: 748132ec-a575-4329-b01b-6171a9cf8478</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">
https://ENROLLTEST.CONTOSO.COM/EnrollmentServer/Discovery.svc
</a:To>
</s:Header>
<s:Body>
<Discover xmlns="http://schemas.microsoft.com/windows/management/2012/01/enrollment/">
<request xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<EmailAddress>user#contoso.com</EmailAddress>
<RequestVersion>1.0</RequestVersion>
</request>
</Discover>
</s:Body>
</s:Envelope>
RESPONSE:
Header:
HTTP/1.1 200 OK
Content-Length: 865
Content-Type: application/soap+xml; charset=utf-8
Server: EnterpriseEnrollment.Contoso.com
Date: Tue, 02 Aug 2012 00:32:56 GMT
<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">
http://schemas.microsoft.com/windows/management/2012/01/enrollment/IDiscoveryService/DiscoverResponse
</a:Action>
<ActivityId>
d9eb2fdd-e38a-46ee-bd93-aea9dc86a3b8
</ActivityId>
<a:RelatesTo>urn:uuid: 748132ec-a575-4329-b01b-6171a9cf8478</a:RelatesTo>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">>
<DiscoverResponse
xmlns="http://schemas.microsoft.com/windows/management/2012/01/enrollment">
<DiscoverResult>
<AuthPolicy>OnPremise</AuthPolicy>
<AuthUrl/>
<EnrollmentPolicyServiceUrl>
https://enrolltest.contoso.com/ENROLLMENTSERVER/DEVICEENROLLMENTWEBSERVICE.SVC
</EnrollmentPolicyServiceUrl>
<EnrollmentServiceUrl>
https://enrolltest.contoso.com/ENROLLMENTSERVER/DEVICEENROLLMENTWEBSERVICE.SVC
</EnrollmentServiceUrl>
<FederatedServiceName/>
<FederatedServicePolicy/>
</DiscoverResult>
</DiscoverResponse>
</s:Body>
</s:Envelope>
I have created many WCF API, some of them are REST.
My main understanding is - don't use it!
WCF is good in enabling you to choose the type of protocol to use between server and client.
Using it you pay in performance and durability.
If you already set your mind on REST (which is an excellent choice) I suggest you dig into ServiceStack. This is by far the most mature, maintained and advanced REST framework for .NET
It is easy to use and helps you build the API correctly, by making many smart choices on the way.
Give it a shot and never look back!

SoapUI get response but not the .Net Client

I am trying to access a https Java webservice from .net client but always end up with "504 Gateway Timeout" exception.
I could get the response from the same webservice using SoapUI.
I also noticed that the request soap message of SoapUI and .net client aren't similar. My question is, does the wrong format of message gives the "504 Gateway Timeout" problem ? if yest, How could i modify the soap message in .net client?
Here are the request soap message that two different app generates:
SoapUI
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://company.domain.com/EchoService/v1_00">
<soapenv:Header/>
<soapenv:Body>
<v1:Echo>test</v1:Echo>
</soapenv:Body>
</soapenv:Envelope>
.NET client
{<s:Envelope xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:s="http://www.w3.org/2003/05/soap-envelope">
<s:Header>
<a:Action s:mustUnderstand="1">Echo</a:Action>
<a:MessageID>urn:uuid:7a76925d-5bf0-4f2d-a9c5-c5a026e1eefb</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Echo xmlns="http://company.domain.com/EchoService/v1_00">test</Echo>
</s:Body>
</s:Envelope>}
sorry, folks nothing to do with wcf binding or soap message but the proxy was blocking the request. SoapUI could send/receive the message because it doesn't use proxy. just changed useDefaultWebProxy="false" in binding section of configuration.

Preventing BizTalk from emitting a "To" Soap header in an outgoing request to a WCF BasicHttp service

Using BizTalk 2010 to consume a WCF webservice with BasicHttp binding.
My service is rejecting the requests coming from BizTalk. I can see using tracing and soapUI that the reason is the "To" header emitted by BizTalk in the outgoing message:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://biztalk01:81/StuffServices.svc</To>
</s:Header>
<s:Body>
<ns0:GetMyStuff xmlns:ns0="http://example.com/stuff" xmlns:ns1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<ns0:inputArray>
<ns1:string>80220</ns1:string>
</ns0:inputArray>
</ns0:GetMyStuff >
</s:Body>
</s:Envelope>
This request gives a fault back both in BizTalk and in soapUI, but if I try in soapUI to send the exact same request without the To header (deleting the "<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://biztalk01:81/StuffServices.svc
"), then it works fine and returns the correct response.
Thus my question: what are my options to make BizTalk not emit that "To" soap header in that outgoing request?
Actually that header was never in the request sent by BizTalk, it was added by WCF tracing in the log. Using Fiddler to capture the real request sent allowed me to see that the problem was elsewhere. It's possible to get the BizTalk query to go through fiddler by adding the proxy http://127.0.0.1:8888 in the binding configuration of the send port.