I have the WSDL of a SOAP web service and I am consuming it via my MVC application.
From adding the WSDL as a web service to my Visual Studio solution it automatically creates a proxy class for me and it handles all the serialization/destabilization for me which is really awesome for a while. I have been using this proxy class to call/send my SOAP request to the web service (with pure c# code and no XML involves) and I got my response message back and everything is working great.
However, there is a need now for me to find what is the exact xml representation of the SOAP message that I am sending to the web service. How can I get/find/make this?
you can do it like this
var serxml = new System.Xml.Serialization.XmlSerializer(request.GetType());
var ms = new MemoryStream();
serxml.Serialize(ms, request);
string xml = Encoding.UTF8.GetString(ms.ToArray());
where xml is your raw SOAP
I have a SOAP service I need to talk to from a C# application. I have a PHP test application that is using the same SOAP service today, using the standard SoapClient.
It is used similar to this:
$options = array(
'login' => $username,
'password' => $password,
'location' => "https://$serveruri/soap",
);
$service = new SOAPClient($wsdl, $options);
$retval = $service->SomeMethod($parameter);
And this works just fine. As far as I understand (I am useless at PHP), since we're not setting an authentication option, it should go with Basic authentication.
I am trying to talk to the same endpoint in C#, and it keeps prompting me for authentication. I am not sure how to recreate the same authentication. I believe some of the problems come from using https - I have been able to talk to a similar system in the past using http and the BasicHttpBinding, but since I have to talk to this one across https, that is no good.
So I have generated a client proxy using SvcUtil, and I am trying to talk to it. Here is my current iteration of desperation:
var endpoint = new EndpointAddress(SoapUrl);
var binding = new WSHttpBinding(SecurityMode.Transport);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
binding.SendTimeout = new TimeSpan(0, 0, 10);
ServicePointManager.ServerCertificateValidationCallback +=
(sender, cert, chain, sslPolicyErrors) => true;
var client = new soapServiceClient(binding, endpoint);
if (client.ClientCredentials != null)
{
client.ClientCredentials.UserName.UserName = Settings.AuthenticationUsername;
client.ClientCredentials.UserName.Password = Settings.AuthenticationPassword;
}
var retval = client.SomeMethod(parameter);
And to address Jons comment below: client.ClientCredentials really is not null, ever, when I run this. ReSharper put that there to stop itself from nagging.
When I run this, I get a 401 Unauthorized from the server. I get the following in Visual Studio 2013:
Additional information: The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Basic realm="bla bla service"'.
How can I get WCF to behave like PHPs SOAPClient in this case?
Is there another binding I should use? I have tried different SecurityMode values, I have tried Digest authentication, but they get me nowhere. Since this happens over https I guess I can't Wireshark it either..
Thankful for any insights!
EDIT: Jon suggested to give Fiddler2 a try. I turned on https decryption and gave it a go.
Two things jump out at me:
1) When I run the PHP script locally (using EasyPHP running on my machine), it contacts the SOAP server and gets data. However, Fiddler2 does not see this traffic in any way.
2) When I run my app in Visual Studio 2013, Fiddler2 does see the traffic, and it decrypts it. I see two attempts to contact the SOAP endpoint; Both get a 401 reply. The first contains no auth information (looking at the Inspectors -> Auth part of Fiddler2) and just says:
No Proxy-Authorization Header is present.
No Authorization Header is present.
Then the second request tries to fix that with an Authorization header that looks kinda like this:
Authorization Header is present: Basic [some hash data]
Decoded Username:Password= [correct username]:[correct password]
But as mentioned - this still provokes a 401 from the other side.
I have no idea why the PHP traffic doesn't show up in Fiddler2, but it very clearly receives live data from the other side. Perhaps PHP doesn't use the network stack in a way that Fiddler2 can pick up, I have no idea.
EDIT 2: After a bunch of filthy debugging on the PHP side, I finally got to compare the request/response cycle of the PHP app with the WCF one. That got me a lot closer (somehow I had gotten a sub character into the auth username, which caused the authentication issue), but now I am struggling with a ProtocolException, caused by my binding being set to Content-Type application/soap+xml, and the external service (I believe this to be Linux based) returning text/xml.
My understanding from abusing Google on this is that text/xml is common for SOAP 1.1, while application/soap+xml is what is used with SOAP 1.2.
Also, I understand that in WCF BasicHttpBinding supports SOAP 1.1, while WsHttpBinding supports SOAP 1.2.
Since this service is on the public internet, it requires https for security. I believe that the original SOAP service on the system itself uses HTTP, but it is behind a gateway that requires HTTPS and then passes it on as HTTP to the actual box serving the requests.
The core of the question then becomes: Is there a way for me to access a SOAP 1.1 service using HTTPS with WCF?
So I've come full circle on this. I started out this morning as a WCF newbie, and while I won't even claim to be a competent user yet, I understand a lot more about the bindings.
By using shotgun debugging I had actually done it correctly a few times, but I was tricked by an invisible sub character (^Z I believe) in the username I copied into my code.
Also, this was compounded by me seeing a lot of information about BasicHttpBinding not supporting https - it does, if you create it like this:
var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
Credit to this relatively old article for educating me to the point of figuring it out:
https://msdn.microsoft.com/en-us/magazine/cc163394.aspx
From this article I also came to the understanding that had BasicHttpBinding not supported https, I could have built my own CustomBinding that worked the same with relatively little effort.
Also thanks to our overlord Jon Skeet for pushing me in the right direction of figuring out what was actually being sent across the wire!
I've built SOAP based client using wsdl file and it works really good. One issue that I am having now is - I need to see original SOAP format messages (requests and responses) that are being sent and received.
It there any way how I can obtain XML requests/responses?
SomeClient Client = new SomeClient();
var response = Client.SomeMethod();
If this is for debugging purposes you could configure tracing: http://msdn.microsoft.com/en-us/library/ty48b824.aspx. Or use Fiddler to capture HTTP traffic.
As part of learning node.js, I just created a very basic chat server with node.js and socket.io. The server basically adds everyone who visits the chat.html wep page into a real time chat and everything seems to be working!
Now, I'd like to have a C# desktop application take part in the chat (without using a web browser control :)).
What's the best way to go about this?
I created a socket server in nodejs, and connected to it using TcpClient.
using (var client = new TcpClient())
{
client.Connect(serverIp, port));
using (var w = new StreamWriter(client.GetStream()))
w.Write("Here comes the message");
}
Try using the HttpWebRequest class. It is pretty easy to use and doesn't have any dependencies on things like System.Web or any specific web browser. I use it simulating browser requests and analyzing responses in testing applications. It is flexible enough to allow you to set your own per request headers (in case you are working with a restful service, or some other service with expectations of specific headers). Additionally, it will follow redirects for you by default, but this behavior easy to turn off.
Creating a new request is simple:
HttpWebRequest my_request = (HttpWebRequest)WebRequest.Create("http://some.url/and/resource");
To submit the request:
HttpWebResponse my_response = my_request.GetResponse();
Now you can make sure you got the right status code, look at response headers, and you have access to the response body through a stream object. In order to do things like add post data (like HTML form data) to the request, you just write a UTF8 encoded string to the request object's stream.
This library should be pretty easy to include into any WinForms or WPF application. The docs on MSDN are pretty good.
One gotcha though, if the response isn't in the 200-402 range, HttpWebRequest throws an exception that you have to catch. Fortunately you can still access the response object, but it is kind of annoying that you have to handle it as an exception (especially since the exception is on the server side and not in your client code).
how to consume php web service in c# Desktop application. I am doing this by adding web reference and through code
WebReference.TestWSDL pdl = new testingApp.WebReference.TestWSDL();
string copy = pdl.verify("testing");
but it throws the error
Possible SOAP version mismatch: Envelope namespace http://schemas.xmlsoap.org/wsdl/ was unexpected. Expecting http://schemas.xmlsoap.org/soap/envelope/.
Make sure you are sending the the appropriate soap version request that the service is expecting ie sending a soap 1.2 request to a service expecting a 1.1 request would give a similar error. Maybe run fiddler and post the messages that are sent and recieved for people to have a look at?