I am currently adding a SOAP-WSDL Service to my project using "Add Service Reference". it creates all necessary classes and functions for me to call. Some of these functions dont give me a response. After 1 minute delay i get a timeout exception. However when i forge the request using Postman (a chrome extension for making network requests) it gets full response. i got suspicious and started to inspect network using Wireshark. after inspection i saw that problem was at the service. but i can't make them fix that. so i need to imitate Postman request using C#.
Main difference between mine and postman is, Postman posts all necessary data in single request for a response, but my client posts just http headers waits for a Http Continue and continues sending necessary data. i guess this breaks the service.
Here are wireshark screenshots for Postman and my client
(Postman is on the left of image and right one is my .net client - sorry for my perfect paint skills)
Is there any configuration on .net wsdl client with basicHttpBinding i can configure to make single request for a call?
edit: when i further investigated my C# client i saw that .net http layer send an initial POST with saying (Expect: 100 Continue), after it receives continue it continues to send SOAP Envelope
edit2: i changed my code to issue request using HttpWebRequest, but .net still sends header and post body with seperate requests (even when i disabled Expect: 100 Continue) and in my theory this breaks service.
question2: is there anyway to say HttpWebRequest, don't split header and body? send all of them in single request?
edit3: i solved the problem. but it wasn't about 100 Continue. service was being broken because of missing User-Agent Header
For HttpWebRequest you can add the following to your .config file - we use this on our service. I'm not, however, sure how it impacts WCF channels.
<configuration>
<system.net>
<settings>
<servicePointManager expect100Continue="false" />
</settings>
</system.net>
</configuration>
i finally solved the problem. after long inspections and tries i saw that remote service stops responding in the middle of the data communication if i dont add User-Agent HTTP Header. so i added http header using IClientMessageInspector before every request
here is wcf code if anybody needs it
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
HttpRequestMessageProperty realProp;
object property;
//check if this property already exists
if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out property))
{
realProp = (HttpRequestMessageProperty) property;
if (string.IsNullOrEmpty(realProp.Headers["User-Agent"])) //don't modify if it is already set
{
realProp.Headers["User-Agent"] = "doktorinSM/2.1";
}
return null;
}
realProp = new HttpRequestMessageProperty();
realProp.Headers["User-Agent"] = "doktorinSM/2.1";
request.Properties.Add(HttpRequestMessageProperty.Name, realProp);
return null;
}
Related
I've wrote a XMPP Server on C#, based on another (OPEN SOURCE) project. That project had a lot of handlers that help me work the XMPP Protocol, but did not have a BOSH Connection manager - so i wrote one.
The idea was to use the standard clients (via TCP Connection) and a Converse.JS on a browser.
The standard clients are working fine, but the Converse.JS had issues. My problem is not handling the bosh requests themselves, but handling the initial OPTIONS request that Converse.JS sends (with an empty body).
According to their forum (where i posted this Issue) the
The OPTIONS request is a so-called preflight request to determine whether the domain being queried supports CORS. IIRC this only happens when making cross-domain requests. If you intend to support CORS, then you'll need to respond appropriately to OPTIONS requests.
And studing that a little, i came up with this solution (that is not working, since Converse.JS keeps sending the OPTIONS request over and over, until it fails to connect):
internal static void SendCORSResponse(HttpListenerContext ctx)
{
ctx.Response.StatusCode = (int)HttpStatusCode.OK; //200
ctx.Response.AddHeader("Access-Control-Allow-Origin", "*");
ctx.Response.AddHeader("Access-Control-Allow-Methods", "GET,POST,HEAD,PUT,DELETE,OPTIONS");
ctx.Response.AddHeader("Access-Control-Allow-Headers", "content-type");
ctx.Response.AddHeader("Access-Control-Max-Age", "86400");
ctx.Response.AddHeader("Accept-Encoding", "gzip");
ctx.Response.AddHeader("Accept-Charset", "utf-8");
ctx.Response.AddHeader("Accept-Language", "*");
ctx.Response.AddHeader("Accept", "*");
ctx.Response.Close(); //sends the response
}
That function is called on the class handling the connection when the header contains the OPTIONS tag. What do i do, or what did i do wrong?
Just for future references - the problem was not in this function; the function i used to detect if the request was null that was wrong and returned true every time.
Problem solved.
I need to consume a third-party WebSocket API in .NET Core and C#; the WebSocket server is implemented using socket.io (using protocol version 0.9), and I am having a hard time understanding how socket.io works... besides that the API requires SSL.
I found out that the HTTP handshake must be initiated via a certain path, which is...
socket.io/1/?t=...
...whereby the value of the parameter t is a Unix-timestamp (in seconds). The service replies with a session-key, timeout information, and a list of supported transport protocols. Due to simplicity, this first request is made via HttpClient and does not involve any additional headers.
Next, another HTTP request is required, which should result in an HTTP 101 Switching Protocol response. I specified the following headers in accordance to the previous request...
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: ...
Sec-WebSocket-Version: 13
...whereby the value of the Key-header is a Base64-encoded GUID-value that the server will use to calculate the Sec-WebSocket-Accept header value. I also precalculate the expected Sec-WebSocket-Accept header value, for validation...
I tried to make that request using HttpClient as well, but that does not seem to work... I actually don´t understand why, because I expect an HTTP response. I also tried to make the request using TcpClient by sending a manually prepared GET request over a SslStream, which accepts the remote certificate as expected. Sending data seems to work, but there´s no response data... the Read-method returns zero.
What do I miss here? Do I need to setup a listener for the WebSocket connection as well, and if yes how? I don´t want to implement a feature complete socket.io client, I´d just like to keep it as simple as possible to catch some events...
The best way of debugging these issues is to use a sniffer like wireshark or fiddler. Often connect using an IE and compare IE results with my application and modify my app so it works like the IE. Using WebClient instead of HttpClient will also work better because the WebClient does more automatically than the HttpClient.
A web connection uses the header of the client and the headers in the server webpage to negotiate a connection mode. Adding additional headers to you client will change the connection mode. Cookies are also used to select the connection mode. Cookies are the results of previous connection to the same server which shortens the negotiations and stores info from previous connection so less data has to be downloaded from server. The server remembers the cookies. Cookies have a timeout and is kept until timeout expires. The IE history in your client has a list of IP addresses and Net automatically sends the cookies associated with the server IP.
If a bad connection is made to the server the cookies is also bad so the only was of connection is to remove the cookie. Usually I go into the IE and delete cookies manually in the IE history.
To check if a response is good the server returns a status. A completed response contains a status 200 DONE. You can get status which are errors. You can also get a 100 Continue which means you need to send another request to get the rest of the webpage.
Http has 1.0 (stream mode) and 1.1 (chunk mode). Net library doesn't work with chunk. Chunk requires client to send message to get next chunk and I have not found a way in Net to send the next chunk message. So if a server responds with a 1.1 then you have to add to your client headers to use 1.0 only.
Http uses TCP as the transport layer. So in a sniffer you will see TCP and HTTP. Usually you can filter sniffer just to return Http and look at header for debugging. Occasionally TCP disconnects and then you have to look at TCP to find why the disconnect occurs.
I am consuming a web service from a url. When I test using SoapUI, I get the response immediately (See image below) and that the request data I sent out made it through to the other end.
So in my C# application I did the same thing, I consumed the web service wsdl and auto generated the proxy class. I create a request based on that proxy class with the exact same request data I used in SoapUI and sent out. I confirmed that at the other end they received my data successfully and no error is shown.
However, I never receive any ID back and after a while I would get this exception:
Error The HTTP request to 'http://someURLWebservice.com/WSoperation' has exceeded the allotted timeout of 00:00:59.9470000. The time allotted to this operation may have been a portion of a longer timeout.
Am I missing something here? I downloaded the WSDL and generated the mock service with SoapUI and if I make a call to that mock web service locally, I would get it right away.the ID back right away.
Here is my code:
string serverURL = Settings.Default.ExtensionServiceURL;
//Get Proxy class client
ext.ExtWSPortTypeClient client = new ext.ExtWSPortTypeClient();
EndpointAddress addr = new EndpointAddress(serverURL);
try
{
client.Endpoint.Address = addr;
Uri site = new Uri(serverURL);
client.Endpoint.ListenUri = site;
ExtensionData eData = new ExtensionData();
client.ChannelFactory.CreateChannel();
Console.WriteLine("Sending Locator Event Request to Web Service");
ext.locatorEventResponse1 resp = await client.locatorEventAsync(eData.GenerateLocatorEventRequest(ev));
}
catch (Exception ex)
{
Console.WriteLine("Error " + ex.Message);
}
finally
{
if (client != null)
{
((ICommunicationObject)client).Close();
}
}
In a similar situation, I would start with the following:
Test with the WCF Client and capture the trace file:
Configure WCF Tracing for the client
(http://msdn.microsoft.com/en-us/library/ms733025(v=vs.110).aspx)
Send the message via your WCF Client Application
Let the call timeout and save the trace log data
Test with the soapUI client and capture the Http Log
Clear the soapUI http log (one of the tabs along the bottom)
Send the message via the soapUI test request
Save the Http Log
Once you have the trace information for both clients, you should be able to compare the transactions and hopefully determine the source of the issue. In particular, I would suggest confirming the service addresses on both sides and then comparing the SOAP envelope to make sure the WCF bindings are set consistently with the soapUI settings.
In addition, you could also use Fiddler to view the web service communications. The following SO post provides good reference links. Fiddler and Monitoring Web Service Traffic
Hope this helps.
Regards,
So I ended up configure Fiddler2 to sniff my SoapUI request and compare it against my application request. In the the Application request header I saw the following:
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Host: engage.ext-inc.com
Content-Length: 1036
**Expect: 100-continue**
That Expect:100-continue is not in the SoapUI request which successfully sent out and got the response. With this in mind I took the SoapUI request in Fiddler and compose a new one base on it...except I put in Expect:100-continue and guess what, I received no response.
Upon reading about it I came across this link
And voila, upon putting ServicePointManager.Expect100Continue = false; into my code prior making the web service call I get the response back right away.
Check the message quota settings, it might be that your service is sending more than what is configured
Issue:
Consider the following working code.
System.Net.WebProxy proxy = new System.Net.WebProxy(proxyServer[i]);
System.Net.HttpWebRequest objRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(https_url);
objRequest.Method = "GET";
objRequest.Proxy = proxy;
First, notice that proxyServer is an array so each request may use a different proxy.
If I comment out the last line thereby removing the use of any proxies, I can monitor requests in Fiddler just fine, but once I reinstate the line and start using them, Fiddler stops logging outbound requests from my app.
Question:
Do I need to configure something in Fiddler to see the requests or is there a change in .Net I can make?
Notes:
.Net 4.0
requests are sometimes https, but i don't think this is directly relevant to issue
all requests are outbound (not localhost/127.0.0.1)
Fiddler is a proxy itself. By assigning a different proxy to your request.. you're essentially taking Fiddler out of the equation.
If you're looking to capture traffic and use your own proxy.. you can't use a proxy (by definition that makes no sense).. you want a network analyzer, such as WireShark. This captures the traffic instead of having the traffic routed through it (as a proxy does), allowing you to have it monitor traffic and route your requests through your custom proxy.
We're consuming a web service (web reference, not service reference), and I need a way to output the entire message being sent (including headers) and the message that gets received.
When I add the web reference, the generated base type of the client object to send the messages is System.Web.Services.Protocols.SoapHttpClientProtocol
I send the messages like so:
ApiService api = new ApiService();
// set the certificate and basic http network credentials
var response = api.SendRequest(messageObject);
I'm able to get the body of the request by serializing messageObject, but can't figure out how to get the full message with the headers.
Since I'm using a certificate and basic authentication, tools like Fiddler, etc. aren't getting me what I need, so I believe I have do something programmatically to pull whats sent and whats received prior to being encrypted with ssl.
EDIT
What I want to see if the data being sent and received to another service from within my WCF service.... e.g.:
// this function is within my WCF service
public ResponseModel Auth()
{
// call to another service here... need to trace this
}
If this is for tracing purposes I have had some success using the tracing capabilities of the System.Net libraries, you should be able to enable the tracing through configuration only.
It's described here: How to: Configure Network Tracing
The resulting log file isn't the easiest to follow, but is described here: Interpreting Network Tracing