I am using HttpClient for sending HTTP requests and receiving HTTP responses in my Windows 8 app. I have few questions on the same:
1) Can I send multiple/parallel HTTP requests using a single HttpClient object? Is there a recommended way to use HttpClient object efficiently?
2) What is the difference when I create HttpClient object every time and when I re-use the same object for each new request?
3) I am tracking the requests and responses using Fiddler. What I found out is that the response time in Fiddler is different than the response time I am calculating manually inside my App. The response time for a request in Fiddler is always lower than the calculated response time in my app. Can anybody please tell me why it is like that?
4) One more thing I came across is that for every request it is doing HTTPS handshake. Instead it should do it only first time. I checked it using Fiddler and it is clearly visible there. Is there any property I need to set in HttpClient object to stop this from doing it every time.
5) Whether HttpClient is thread-safe?
1 & 5:
HttpClient manual:
The following methods are thread safe:
CancelPendingRequests
DeleteAsync
GetAsync
GetByteArrayAsync
GetStreamAsync
GetStringAsync
PostAsync
PutAsync
SendAsync
2 & 4:
HttpClient manual:
The HttpClient class instance acts as a session to send HTTP requests.
3:
Fiddler acts as a proxy. Your browser sends the request to Fiddler, which forwards it to the origin server. This adds upon the request time.
Make sure that you use the same HttpClient object for each async HttpRequest which will prevent it from overlapping the requests
Related
I have number of APIs which is not being hosted by me, so I have no control of the API itself. What I'm trying to achieve is to check whether the APIs is online or not.I already tried several way:
Sent a HTTP request to the API endpoint with HEAD method
Sent a blank HttpWebRequest
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
if (response.StatusCode == HttpStatusCode.NotFound)
return false;
return true;
}
Ping the server
But somehow my end result is not accurate enough. It shows offline but when I manually try to invoke the API, it seems okay. Anybody got a solution?
What about using an API Health Check service?
Some links that can help you:
https://www.runscope.com/
https://www.getpostman.com/docs/postman/monitors/intro_monitors
https://blog.runscope.com/posts/build-a-health-check-api-for-services-underneath-your-api
https://nordicapis.com/monitor-the-status-of-apis-with-these-4-tools/
https://apigee.com/about/blog/technology/api-health-free-tool-monitoring-apis-public-beta-now
The first option should be good as long as the server can respond to a HEAD request. If it doesn't there should be some safe GET endpoint which can be used instead.
It also makes sense to time the health check so that if the API server is not alive, it won't freeze your app.
You can use Postman Monitors to achieve this. Postman offers 1000 free monitor runs on the free account and notifications via email on failures. You can set it up to run on a schedule by specifying the hour/day/week that the monitor should run at.
Simply create a postman collection: https://learning.getpostman.com/docs/postman/collections/creating_collections/
Add your HTTP Health check request in the collection.
Create a monitor on the collection: https://learning.getpostman.com/docs/postman/monitors/setting_up_monitor/
And set up the frequency that it should run with.
You can also manually trigger monitors via the Postman API: https://docs.api.getpostman.com
I have to send two HTTP requests: The second one should be sent while I'm waiting for response from the first one. The responses should be received independently, so it can happen that either response can arrive first. How do I do this in C#? Should I use 2 HttpClients or not and how?
Yes I have resolved it. I'm making 2 HttpRequestMessage, then twice httpClient.SendAsync(request)
so it is
var a=httpClient.SendAsync(request1);
var b=httpClient.SendAsync(request2);
and then I'm getting both responses like
a.GetAwaiter().GetResult();
b.GetAwaiter().GetResult();
This question already has answers here:
Do HttpClient and HttpClientHandler have to be disposed between requests?
(12 answers)
Closed 5 years ago.
From this answer to the question: Do HttpClient and HttpClientHandler have to be disposed?, I see that the best practice is not to dispose a System.Net.Http.HttpClient per HTTP request. In particular, it is stated that:
standard usage of HttpClient is not to dispose of it after every request.
And that is fine.
My question is, does this "pattern" apply to Windows.Web.Http.HttpClient as well? Or should it be disposed per HTTP request? I think the documentation is a bit vague on this. In one of the samples, it simply states:
// Once your app is done using the HttpClient object call dispose to
// free up system resources (the underlying socket and memory used for the object)
httpclient.Dispose();
I believe this can be read both ways, so any specific input on this is appreciated.
It seems to me that if it were intended to be used for only one request at a time, it would simply throw an exception if you tried to use it for more than one.
Also, consider that all but the earliest version of HTTP allows multiple requests for a given TCP connection. Using the same HttpClient object allows the framework to maintain a TCP connection for multiple requests.
While it's true that the sample code performs just one request, note this text in the documentation:
The HttpClient class instance acts as a session to send HTTP requests and receive responses. An HttpClient instance is a collection of settings that apply to all requests executed by that instance. In addition, every HttpClient instance uses its own connection pool…
[emphasis mine]
For the object to act as "a collection of settings that apply to all requests executed by that instance", it is obvious it would have to be used for more than one request.
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;
}
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.