How to test a WCF Webservice with JMeter? - c#

I have a WCF Webservice hosted on IIS which exposes a single method that takes three integer parameters. I have a simple, console based client which can call this method.
int InsertNewOrder(short quantity, int custID, int productID);
If my understanding is correct, I need to provide JMeter a SOAP envelope with the details of the method to be called and parameters to be passed. I have seen many examples similar to below:
<soapenv:Envelope xmlns:soapenv="schemas.xmlsoap.org/soap/envelope/">;
<soapenv:Body>
<ns2:InsertNewOrder xmlns:ns2="?????">
<ns2:Param1>${1}</ns2:Param1>
<ns2:Param1>${1}</ns2:Param1>
<ns2:Param1>${1}</ns2:Param1>
</ns2:InsertNewOrder>
</soapenv:Body>
</soapenv:Envelope>
However, from looking at my WSDL doc, I don't see where it refers to any of the parameters needed to pass to the method. I've also used Fiddler to examine the client's soap messages to the service. Again, I don't see where it's passing the parameters. As a result, I don't know how to create a simple SOAP envelope I can use with JMeter to test this service.
Can anyone advise as to why the WSDL doc does not provide any details of the method parameters, or explain how I can create the necessary SOAP envelope for use with JMeter?
I am coding in C# using VS 2010, JMeter 2.4, IIS v6, wsHttpBinding.

Disclaimer: I'm not a WSDL expert, so i can't tell you why the doc doesn't provide detail.
To generate the SOAP envelope for JMeter, I've used the free version of soapUI.
Steps
Import WSDL into soap
Create a default request for the method
Set the request view to RAW, and copy into JMeter
This provides me all the information I need for jmeter, including parameters, user-agent, endpoint, etc.

Use JMeter's "HTTP Proxy Server" to record the WCF calls with your normal testclient, and then play them back later when testing. This is what I have experienced to be fastest, and gives the best test-cases (because you record them with your normal client, or test client of choice).
Set up JMeters HTTP Proxy Server as per instructions. Then, make sure the WCF (or any SOAP) client use that proxy. The important part of the WCF client configuation is (replace my ... with normal config):
<system.serviceModel>
<bindings>
...
<wsHttpBinding>
<binding ... proxyAddress="http://proxyServerName:8080" useDefaultWebProxy="false" ...>
...
<security mode="None">
<message establishSecurityContext="false"/>
<transport clientCredentialType="None"/>
</security>
proxyServerName is localhost, if the WCF client runs on the same machine as JMeter (normal when creating the test cases).
Also, I got an error message using HTTP Proxy, if I did not turn off security as shown above. The same security settings must also be at the WCF service server.
Happy testing! :-)

Related

How to consume a soap web-service in c# and pass XML in request?

I need your help to find the best way to call a soap web-service in c# ?
I know using the web-service reference feature in c# is a good one.
I tried using it and it did not work ?
Here is the xml that I want to post
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:cus="http://temenos.com/CUSTDETS">
<soapenv:Header/>
<soapenv:Body>
<cus:EDBCUSTDETS>
<WebRequestCommon>
<!--Optional:-->
<company></company>
<password></password>
<userName></userName>
</WebRequestCommon>
<EDBCUSTDETSType>
<!--Zero or more repetitions:-->
<enquiryInputCollection>
<columnName></columnName>
<criteriaValue></criteriaValue>
<operand>EQ</operand>
</enquiryInputCollection>
</EDBCUSTDETSType>
</cus:EDBCUSTDETS>
</soapenv:Body>
</soapenv:Envelope>
After adding the reference for the WSDL in the service references folder, I named it as ServiceReference1.
Now I Can see in my code :
How to achieve this request ?
how can I add company, password and user Name and the enquiryInputCollection parameters ?
Is there any best practice for achieving this ?
Thanks.
If you have successfully generated proxy classed from WSDL, then you should be good to go. I assume you should have been provided web service documentation for consuming them.
Look for service client classes to begin with.
eg:
var client = new ServiceReference1Client();
client. ? //(should list Methods and you can find Types of Paramaters to build them.)
If you check in web.config/app.config, and if you see and <client> and <endpoint />, this is where you supply endpoint address. If you need to send client certificate you might want to start with either or and setting security eg:
<security mode="Transport">
<transport clientCredentialType="Certificate" />
</security>
There are lot of resources on WCF capabilities to achieve this. Hope this helps mate.

WCF client exception: Unrecognized message version

I hit this error today when deploying a WCF client to QA:
System.ServiceModel.CommunicationException: Unrecognized message version.
In Fiddler I noticed that the WCF client sends its request wrapped in a SOAP Envelope (as expected) but that the response from the remote web service is not wrapped in a SOAP Envelope. That is, our local debug web service sends a response like this:
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header />
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Response xmlns="urn:example">
<Success>true</Success>
...
</Response>
</s:Body>
</s:Envelope>
But the remote web service is just sending this:
<?xml version="1.0" encoding="utf-8"?>
<ns0:Response xmlns:ns0="urn:example">
<ns0:Success>true</ns0:Success>
...
</ns0:Response>
As far as I can tell the WCF client is throwing the exception because there's no SOAP Envelope. So my questions are:
Is my assumption correct or should be I looking elsewhere?
Is there some way to configure the WCF client's bindings to remove the SOAP Envelope expectation?
Should I just tell the remote service implementor to fix their service (which they wrote just for us from a supplied WSDL)?
The WCF client is using basicHttpBindings (and HTTP Basic Authentication over SSL/TLS). I'd considered using IClientMessageInspector.AfterReceiveReply() to rewrite the response but the exception gets thrown before that method is invoked, i.e.: We already have an implementation of it for request/response logging and it's not hitting a breakpoint in there.
More info:
After communicating with the service developer it sounds like they completely ignored the .wsdl and (svcutil generated) IService.cs files we gave them and wrote a POX (Plain-Old XML) service from scratch.
I'm not confident that we can convince them to do it properly, so now I'm looking for tips to convert a properly behaving WCF SOAP client into a POX client.
This may be caused by that your service uses Soap1.2 while you are using a different version to call it.
Please try "Add Service Reference" - "Advanced..." - "Add Web Reference..." as a compatibility approach.
I had this issue as well. I know this is an older post, but in my case I modified the app.config file in my C# .NET app that calls this web service. I think it was adding
<security mode="Transport" />
to the basicHttpBinding element that solved it. I also extended the timeouts and maxBufferPoolSize.
Microsoft has documentation that describes this, in case this helps someone else.

Increase timeout when consumed as web reference (not service reference)

There are lots of similar questions on StackOverflow. If this is a duplicate, I would appreciate a little explanation of how to apply other solution in my context please.
I have a project that is a WebAPI. This WebAPI in turn calls a web service (WSDL), processes the data and returns to the client:
[Client] ----> [My WebAPI] ----> [WSDL Server]
|
<-------- [My WebAPI] <---------
The WSDL part is a Java-based service. The only way we could consume it without issue in VS2015 was to add it as a Web Reference (2.0 in the dialog). It works perfectly, with strongly-typed values as required, but today we've seen a timeout between My WebApi and WSDL Server.
In other answers on SO, I see that the timeout period can be configured in web.config <bindings> or via a proxy, but I can't see how to wire this up given my web.config contents, which differs massively from other peoples. The code below was generated by VS2015 when the WSDL service was consumed:
<system.serviceModel>
<bindings />
<client />
</system.serviceModel>
<applicationSettings>
<MyWebAPI.Properties.Settings>
<setting name="MyWebAPIs_ThirdPartyWSDLService_GetData" serializeAs="String">
<value>https://wsdl.domain.com/webservices/services/GetData</value>
</setting>
</MyWebAPIs.Properties.Settings>
</applicationSettings>
I also can't find any mention of timeouts in the c# intellisense code. Any help or pointers would be appreciated. I've read about 12 posts on SO but still can't figure it out.
I hate to answer my own question but I think I've found the answer (I will remove if not). This is obvious, but reading too much on SO actually threw me off course and I was inspecting the wrong class in VS.
When consumed, the third-party web service client class GetData() is forced to derive from SoapHttpClientProtocol. This class derives from HttpWebClientProtocol, derived from WebClientProtocol.
WebClientProtocol has a public property Timeout, expressed in milliseconds.
Indicates the time an XML Web service client waits for the reply to a synchronous XML Web service request to arrive (in milliseconds).
The time out, in milliseconds, for synchronous calls to the XML Web service. The default is 100000 milliseconds.
Setting the Timeout property to Timeout.Infinite indicates that the request does not time out. Even though an XML Web service client can set the Timeout property to not time out, the Web server can still cause the request to time out on the server side.
Therefore the Timeout property is available directly from code when instantiated as a web service client, which I believe is due to the magic of VS:
SomeComsumedWebService wsc = new SomeComsumedWebService();
SomeComsumedWebService.Timeout = 600000; // 10 minutes
var obj = SomeComsumedWebService.MethodToGetData();

Sending a "larger" collection of data to an Azure WCF Service

I'm trying to create a web service using Azure.
For the time being, everything is being run locally. The web service and Azure work fine, a simple string Test() method which returns "Hello world" works without problems, as you'd expect. ;)
Now, I've created two methods which add rows to Azure Data Tables. The first sends (using a special DataContract) a single row of data, and this works fine.
The second is for sending larger amount of data, and sends an IEnumerable. So, to test the service, I've created a client application which creates a number of random data to send. If I create up to 42 rows and send that, all goes well.
Above that, I get a 400 Bad request error.
The problem is that there's no inner message to work with (or rather, that WAS the inner message). I strongly suspect it has to do with the size of the request however.
Note, that if I put a breakpoint on the service's method, it doesn't even get that far. I've read quite a few various forum posts regarding similar issues, but those seemed to deal with ordinary WCF services, not Azure ones, and so the Web.config file doesn't contain definitions for bindings nor endpoints, which would be something I could work with.
Please help.
PS. I realise I may have posted very little information. If something else is needed, please ask, and I'll do my best to include it.
Adding the following lines to the Web.config file (under system.serviceModel) in the Azure service project (NOT the Web.config in the client application) resolved the issue:
<bindings>
<basicHttpBinding>
<!--The basicHttpBinding is used for clients which use the generated code to transmit data; the following
settings make it possible to send larger amounts to the service-->
<binding maxReceivedMessageSize="10000000" receiveTimeout="01:00:00">
<readerQuotas maxStringContentLength="10000000" />
</binding>
</basicHttpBinding>
</bindings>

IMetadataExchange endpoint purpose

What is the purpose of IMetadataExchange endpoint. Some places i found that if i dont define this endpoint, adding service reference will not work OR creating proxy using svcutil wont work. But both of this working without having IMetadataExchange defined.
If we have other endpoint with httpGetEnabled = true, we are able to create proxy from client.
Also, some article says that we should delete IMetadataExchange before moving code to production and it should development period only so that other client cant see metadata. Doesnt this stop the behaviour of service having self describing itself?
And if I have defined this IMetadataExchange endpoint, how can i see that on browser. Address whoch i have provided for this endpoint is not pulling any metadata in browser.
Service metadata can be served two ways:
Regular WSDL served over HTTP/HTTPS, which is what that http[s]GetEnabled=true enables.
WS-MetadataExchange (MEX) which uses SOAP (and not just a plain GET request over HTTP) and supports a few more advanced scenarios (in theory, at least). That's what the IMetadataExchange endpoint enables.

Categories

Resources