WCF Service custom message inspector - c#

I built a WCF Service that uses custom username and password authentication and I am testing it from the client app with the following code:
using (ServiceReferenceClient.TestServiceClient tc = new ServiceReferenceClient.TestServiceClient())
{
tc.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
tc.ClientCredentials.UserName.UserName = "User1";
tc.ClientCredentials.UserName.Password = "Pwd1";
tc.ServiceMethod(param1, param2, param3);
}
It works fine but I need to see the actual SOAP request sent to the WCF service and response. How can I do that from my client?
I know I might have to write my own custom message inspector and would like some pointers on how to build one

The options mentioned in the comments above are good for testing. If you want something more robust that you can include in your code, then I think what you want to implement is a WCF Message Inspector.
More on how to do this on the client:
You can inspect or modify the incoming or outgoing messages across a
WCF client by implementing a
System.ServiceModel.Dispatcher.IClientMessageInspector and inserting
it into the client runtime.
https://msdn.microsoft.com/en-us/library/ms733786(v=vs.110).aspx
And a good example:
https://weblogs.asp.net/paolopia/writing-a-wcf-message-inspector

Related

ServiceStack Renaming SyncReply Client

I am looking at using a ServiceStack web service in place of an existing third-party web service. I have matched the DTOs used by the third-party service. However, the client is expecting a proxy class named "NotificationServiceClient", like this:
var client = new NotificationService.NotificationServiceClient();
var response = client.SendNotification(message);
I am unable to alter the source code for the client application, so I would like to configure ServiceStack to use NotificationService for the client proxy, instead of SyncReply. Is there a way to do this?
UPDATE - It seems what I'm looking for is a way to configure ServiceStack so that it generates a different value for the name attribute of the wsdl:service tag; from SyncReply to NotificationServiceClient. I can save the current WSDL, manually manipulate it, and verify the proxy class name using a throw-away client.
Don't use ServiceStack's .NET Service Clients for consuming 3rd Party APIs, they're only designed and opinionated towards consuming ServiceStack Services.
The only HTTP Client we recommend for calling 3rd Party APIs is HTTP Utils which is a our general purpose HTML client.
Based on the comment by mythz, I have overridden the GenerateWsdl in my AppHost, and set the ServiceName property on the wsdlTemplate. Here's an example:
public override string GenerateWsdl(WsdlTemplateBase wsdlTemplate)
{
wsdlTemplate.ServiceName = "NotificationService";
return base.GenerateWsdl(wsdlTemplate);
}

Can ServiceStack mimic a WCF response?

I'm trialling out ServiceStack and loving what I'm seeing so far. However I've run into a bit of a brick wall.
I have a system retrieving data from another system via web services - a service at both ends. These two systems are from different vendors - so I have no control over changing them - and are configured to talk to each other via WCF web services. Let's say "Lemon" calls "Orange" to get some information about a customer.
The way we implement these two systems is slightly different to what the vendors planned - we point their service configuration to our intermediary service - let's call it "Peach" - which goes off and does some other things before returning the information. For example, "Lemon" calls what it thinks is "Orange" but is actually our intermediary service "Peach" using the same method names. "Peach" calls "Orange" for the customer information and for example overrides the email address for the customer with something else before combining all the information appropriately and returning it to "Lemon" in the format it was expecting.
I would like to get "Peach" using ServiceStack. However it's responses needs to be identical to a WCF service returning via wsHttpBinding. Is this possible with ServiceStack? Would it involve overriding the Soap 1.2 type?
Thanks for your help!
If ServiceStack's built-in SOAP Support doesn't return the response you're after, you may need to return the exact SOAP response you're after as a raw string.
Raw Access to WCF SOAP Message
To access the WCF's Raw Request in your Service you can use the IRequiresSoapMessage interface to tell ServiceStack to skip de-serialization of the request and instead pass the raw WCF Message to the Service instead for manual processing, e.g:
public class RawWcfMessage : IRequiresSoapMessage {
public Message Message { get; set; }
}
public class MyServices : Service
{
public object Post(RawWcfMessage request) {
var requestMsg = request.Message... //Raw WCF SOAP Message
}
}
Creating custom WCF Response
Some level of customization is possible by creating a custom WCF Message response and returning the raw output as a string, e.g:
var wcfResponse = wcfServiceProxy.GetPeach(...);
var responseMsg = Message.CreateMessage(
MessageVersion.Soap12, "urn:GetPeach", wcfResponse);
return responseMsg.ToString();
Otherwise you may need to use a HTTP Client like Http Utils to POST raw SOAP to the WCF Service and return the raw string Response.
This question isn't specifically related to WCF. What WCF returns is not a construct of WCF, it is returning a standards based response as specified by the WS* standards. http://en.wikipedia.org/wiki/List_of_web_service_specifications lists many of the standards.
Your question isn't specifically making ServiceStack emulate WCF, it is for ServiceStack to return responses adhering to existing published standards. Standards that WCF has already built in with the WsHttpBinding configuration.

Consuming a web service using POST instead of the going the usual WSDL route

This is how I have currently managed to consume a particular Microsoft web service. Notice that it is located on an HTTPS server and that it requires a username, a password, and a .cer file to be installed in the operating system's "root certificate authorities".
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Message.AlgorithmSuite
= System.ServiceModel.Security.SecurityAlgorithmSuite.Default;
binding.Security.Message.EstablishSecurityContext = true;
EndpointAddress endpoint = new EndpointAddress("https://address.of.service");
//"GreatClient" was created for me automatically by running
//"svcutil.exe https://address.of.service?wsdl"
GreatClient client = new GreatClient(binding, endpoint);
//Username and password for the authentication. Notice that I have also installed
//the required .cer certificate into the system's "root certificate authorities".
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
//Now I can start using the client as I wish.
My question is this: How can I obtain all the information necessary so that I can consume the web service with a direct POST to https://address.of.service, and how do I actually perform the POST with C#? I only want to use POST, where I can supply raw XML data using POST directly to https://address.of.service and get back the result as raw XML data. The question is, what is that raw XML data and how exactly should I send it using POST?
(The purpose of this question: The reason I ask is that I wish to consume this service using something other than C# and .NET (such as Ruby, or Cocoa on Mac OS X). I have no way of knowing how on earth to do that, since I don't have any easy-to-use "svcutil.exe" on other platforms to generate the required code for me. This is why I figured that just being able to consume the service using regular POST would allow me to more easily to consume the service on other platforms.)
What you are attempting to do sounds painful to do now and painful to maintain going forwards if anything changes in the server. It's really re-inventing the wheel.
If you haven't considered it already, I would:
(a) Research whether you can use the metadata you have for the service and use a proxy generator native to your target plaform. There aren't many platforms that don't have at least some tooling that might get you part of the way if not all of it. Perhaps repost a question targetting Ruby folk asking what frameworks exist to consume an HTTPS service given it's WSDL?
(b) Failing that, if your scenario allows it I would consider using a proxy written in C# that acts as a facade for the service which translates it into something easier to consume (for example, you might use something like ASP.NET MVC WebAPI which is flexible and can easily serve up standards compliant responses over which you can maintain total control).
I suspect one of these may prove easier and more valuable than the road you are on at the moment.
I had to go through something similar when porting .NET WCF code to other platforms. The easiest approach I found was to enable message logging on the WCF client. This can be configured to save both envelope and body and once everything is working on the .NET side of the house, you can use the message log to have "known-good" XML request/response to port to other platforms.
I found this approach to be more elegant since I didn't have to add an additional behavior to log messages, and it can be easily enabled/disabled/tweaked in the config. The Service Trace Viewer Tool that ships with Visual Studio is also handy for reviewing the log files.
I think when you say that the service should be consumed from other platforms, which do not have proxy class generation logic, you can go with REST services. This will allow you to create input as simple string concatenation instead of complex XML. Though its applicability depends on the situation.
Check this discussion : http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/6907d765-7d4c-48e8-9e29-3ac5b4b9c405/
As far as the certificate is concerned, refer http://msdn.microsoft.com/en-us/library/ms733791.aspx on how to configure it.
I know this is not a very precise answer, but you will be the best person to evaluate above procedure, hence posted. Hope it helps.
What I'll do:
1- Create a small c# app that can post on this webservice (using svcutil). And modify it to show the XML send/received. To view the xml there are several ways: logging, wireshark etc. To add it directly to the small app there is another question here that give a good answer.
2- Once you know what you have to send, you can do it in c# like this:
// implement GetXmlString() to return the XML to post
string xml = GetXmlString();
// create the url
string url = new UriBuilder("http","address.of.service",80).ToString();
// create a client object
using(System.Net.WebClient client = new System.Net.WebClient()) {
// performs an HTTP POST
client.UploadString(url, xml);
}
I'm not a .NET programmer but I've had to interoperate with a few .NET services and have lots of SOAP/WSDL experience. Sounds like you've captured the XML for your service. The other problem you'll face is authentication. OOTB, .NET web services use NTLM for authentication. Open-source language support for NTLMv2 can be hit and miss (although a quick google search pulled up a few possibilities for ruby), and using NTLM auth over HTTP may be something that you have to wire together yourself. To answer a question above: where are the auth creds? If the service is using NTLM over the wire, authentication is happening at some layer below HTTP. If the service is using NTLM to authenticate HTTP, your NTLM creds are in the HTTP Authorization header. You should be able to tell with wireshark where they are. You'll also probably need a SOAPAction header; this can also be sniffed with wireshark. For the C# client, I'm sure there are docs explaining how to add headers to your request.

I am trying to consume a PHP SOAP service from C# and create a class wrapper in VS 2010

I've been tasked with creating a class wrapper for a SOAP service, the idea is that you'll be able to treat it as a regular class. The main reason for this is that the WDSL for the SOAP service contains only one method and it's got 5 parameters and it's only kind of OO so you'd have to know all the method calls really well and it's a bit hard to remember them all.
OK, so I've tried adding a web reference, now web references can now be added as service references in VS 2010. You click add service reference advanced etc and it puts in a service reference. Great. Unfortunately if I try and access this from a class I can't.
I can build a console app and put code in the main procedure and access the method of the SOAP service fine but when I add a reference to a class library the intellisense won't allow me to select anything. I'd instantiate an instance like so:
SOAPService.webServiceService ws = new SOAPService.webserviceService();
ws.
and then the intellisense refuses to kick in. If I do the same in a web project or a console app then I can access it fine. I've added the namespace I've done all kinds of things. Also, I can add a web reference and get a DISCO file whenever I create a web project.
OK, also while I'm on the subject I also need to pass credentials to the web service in PHP.
The problem is that in the past I'd create some .net system credentials and add these and it would usually pass through if I was connecting to another .net service.
How should I be sending them to a PHP web service? I always get either invalid username/password combo errors or envelope malformatted error types
Thanks
Mr. B
So the intellisense is not working, but if you add the method in and try to use it does it work, or produce an error?
With regard to diagnosing authentication issues try using fiddler to view the SOAP messages that are being sent, and to view the reply. Do you have some other software that connects and authenticates to that service? Use fiddler to look at the SOAP messages and compare them to see if the header is different etc.
I'd normally do it like this,
using (Service service = new Service())
{
service.ClientCredentials.Windows.ClientCredential.Domain = "domain";
service.ClientCredentials.Windows.ClientCredential.Password = "password";
service.ClientCredentials.Windows.ClientCredential.UserName = "username";
}
Also with regard to the service working or not in general use fiddler if you have any problems, you can see the SOAP messages and it often gives you a clearer message.
I know in IIS you can turn on failed request handling that also gives you an insight from what is going on at the server end, perhaps you have some form of logging too for your php service?

See the SOAP request from Proxy class method calls

I'm using .NET 2.0 web services. If I add a reference to a WSDL and make a proxy class method call, what's the easiest way in VS to see the SOAP being sent?
Example, I added the PayPal WSDL Web Service Reference and made a call as so:
PayPalAPIAASoapBinding _client = new PayPalAPIAASoapBinding();
...rest of code and then
SetExpressCheckoutResponseType checkoutResponse = new SetExpressCheckoutResponseType();
checkoutResponse = _client.SetExpressCheckout(request); // makes the call here
I tried setting a debug point on line 2 but not sure how to dive in to see the SOAP. Obviously I could use something like Fiddler but want to just use Intellisense during debugging to drill down to the object that has the request. I would assume client would have it, my instance above but could not find it. Client is an instance of the PayPal Service.
I do see when I drill down into the base class PayPalAPIAASoapBinding that there is a version property but I can't get the value for this:
System.Web.Services.Protocols.SoapProtocolVersion.Default
when I try to paste that into my watch window, the value just shows the word Default not the true value that's sent. So this is why I need to look at the SOAP and so far in that binding object I don't see a property holding it. But it's gotta be somewhere in any requests you make in a web service in .NET, just don't know where to look during debug?
My end goal here is to be able to read the SOAP envelop before it's being sent really using any WSDL reference in VS.
There's no very easy way. See the example in the SoapExtension documentation on MSDN for a way to log the information.
If you were using WCF, you could just turn on logging in the configuration.
The easiest way to see the SOAP messages (regardless of the programming language) is to use a tool like SoapUI or TCPmon which lets you intercept send and received messages.
This is very easy (if the SOAP is not encrypted). Although it is not in VS.
The easiest way is to use the Fiddler. You can let your VS make Soap calls and see the traffic in raw view on the Fiddler. If the Soap calls are made over SSL, there are some extra steps that needs to be taken for Fiddler to trace them.

Categories

Resources