C# httpclient request size/bandwidth - c#

Basically I'm sending a http post request using HttpClient, but the total response of the kb is roughly 60kb, however I only need to read the response url to determine the outcome, is there anyway I can just read response url rather than the entire data?
Example of the code I'm currently using
string URI = "example.com";
var client = new HttpClient();
var response = await client.PostAsync(URI);
var content = await response.Content.ReadAsStringAsync();
string source = content.ToString();
return source;
What this does is return the body content of " Example.com " but I later realised I wouldn't need to read the body content for a string to determine the outcome, but just simply get the response urls.
I assume this would decrease the size of the request drastically if I'm able to receive the response url of the post request without receiving the body content or other content.

Try to use HttpCompletionOption with proper overload of SendAsync method and rewrite your code like
var request = new HttpRequestMessage(HttpMethod.Post, url);
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);

Related

Is there a way to reorder the data sent in a multipart form POST request?

I am making a request to an external API which needs data in a multipart form to be sent in a specific order.
I have two parameters for the request, one is a JsonParameter and the other is a file.
The issue I am having is I need the JsonParameter to come first in the form data request but cannot find a way to do that currently. I have tried simply changing the order I add to the request but this doesn't seem to affect the order when the request is sent.
This is my current code for the request:
var client = new RestClient(baseUrl);
var request = new RestRequest(endpoint, Method.Post);
request.AlwaysMultipartFormData = true;
var json = JsonConvert.SerializeObject(profile);
var jsonParam = new JsonParameter("profile", profile);
request.AddParameter(jsonParam);
var filename = "test.txt";
var bytes = File.ReadAllBytes(filepath);
request.AddFile("file", bytes, filename, "text/plain");
request.AddHeader("X-auth-token", bearerToken);
var res = await client.ExecuteAsync(request);
Is this possible using restsharp so that the JsonParameter will always come first in the request?

How do I return the HTTP status code when I'm making a JSON post in C#?

I don't understand the variable types and how i can utilize client to retrieve the http Status code.
The client variable is a standard HttpClient object.
The attached picture is the function I'm trying to retrieve the status code during. Any help would be greatly appreciated.
[1]: https://i.stack.imgur.com/9iR3g.png
It should be easy as
var client = new HttpClient();
var results = await client.GetAsync("https://stackoverflow.com");
Console.WriteLine(results.StatusCode);
Your issue is that you're not getting response object. You are getting the content of the body of the response.
Here is a sample code:
void SimpleApiCall()
{
Uri endpoint = new Uri("https://www.7timer.info/bin/");
using var client = new HttpClient();
client.BaseAddress = endpoint;
// Get the response only here, and then get the content
// I'm using GetAwaiter().GetResult() because client.GetAsync() returns a Task and you're not using the async await since this is a button click event
var response = client.GetAsync("astro.php?lon=113.2&lat=23.1&ac=0&unit=metric&output=json&tzshift=0").GetAwaiter().GetResult();
// Status code will be available in the response
Console.WriteLine($"Status code: {response.StatusCode}");
// For the Reason phrase, it will be Ok for 200, Not Found for a 404 response...
Console.WriteLine($"Reason Phrase: {response.ReasonPhrase}");
// read the content of the response without the await keyword, use the .GetAwaiter().GetResult()
var content = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Console.WriteLine("Content:");
Console.WriteLine(content);
}
Same goes for PostAsync and all the other operations...

Is there a HTTP Completion Option for a post request in System.Net.Http?

I want to send a post request but to speed things up not to download the entire page, just the head (or some smaller section of the content). I know there is a way you can do this with get requests but I need to do this with a post request.
I am programming with c# and System.Net.Http. However, I am willing to use another library if its necessary.
Here is how the get request can only download headers:
var request = new HttpRequestMessage(HttpMethod.Get, url);
var getTask = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
And here is my current code:
var response = await client.PostAsync(url, content);
var responseString = await response.Content.ReadAsStringAsync();
You can just change HttpMethod.Get to HttpMethod.Post in your first sample, and assign to request.Content:
var request = new HttpRequestMessage(HttpMethod.Post, url)
{
Content = content,
};
var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
Of course, calling response.Content.ReadAsStringAsync() negates the point of using HttpCompletionOption.ResponseHeadersRead.
HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Head, "your url");
httpClient.SendAsync(httpRequestMessage);

Finding result of POST in Http Response Message

I am building REST Client (c#) using windows form application in VS2017. I have been able to successfully GET and POST requests from the server using the HttpClient.PostAsJsonAsync() and ReadAsync() methods. I am trying to POST some data to the server and upon a successful POST, the server responds with a unique string like "1c77ad2e-54e0-4187-aa9d-9a55286b1f7a"
I get a successful response code (200 - OK) for the POST. However, I am not sure where to check for the resulting string. I have checked the contents of HttpResponseMessage.Content
static async Task<HttpStatusCode> PostBurstData(string path, BurstRequest
burstRequest)
{
HttpResponseMessage response = await client.PostAsJsonAsync(path, burstRequest);
response.EnsureSuccessStatusCode();
Console.WriteLine(response.Content.ToString());
// return response
return response.StatusCode;
}
The data sent to this function call is as follows:
BurstRequest request = new BurstRequest();
request.NodeSerialNumbers = SubSerialList;
request.StartTime = ((DateTimeOffset)dateTimePicker1.Value).ToUnixTimeMilliseconds();
HttpStatusCode statusCode = new HttpStatusCode();
statusCode = await PostBurstData(post_burst_url, request);
Where should I search for the string the server responds for a successful POST? Should the content be read using ReadAsync()?
if (response.IsSuccessStatusCode)
{
var data = await response.Content.ReadAsAsync();
}
Why not trying to use HttpContent like below:
using (HttpResponseMessage response = await client.GetAsync(url)) // here you can use your own implementation i.e PostAsJsonAsync
{
using (HttpContent content = response.Content)
{
string responseFromServer = await content.ReadAsStringAsync();
}
}

How to get the file size from http headers

I want to get the size of an http:/.../file before I download it. The file can be a webpage, image, or a media file. Can this be done with HTTP headers? How do I download just the file HTTP header?
Yes, assuming the HTTP server you're talking to supports/allows this:
public long GetFileSize(string url)
{
long result = -1;
System.Net.WebRequest req = System.Net.WebRequest.Create(url);
req.Method = "HEAD";
using (System.Net.WebResponse resp = req.GetResponse())
{
if (long.TryParse(resp.Headers.Get("Content-Length"), out long ContentLength))
{
result = ContentLength;
}
}
return result;
}
If using the HEAD method is not allowed, or the Content-Length header is not present in the server reply, the only way to determine the size of the content on the server is to download it. Since this is not particularly reliable, most servers will include this information.
Can this be done with HTTP headers?
Yes, this is the way to go. If the information is provided, it's in the header as the Content-Length. Note, however, that this is not necessarily the case.
Downloading only the header can be done using a HEAD request instead of GET. Maybe the following code helps:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://example.com/");
req.Method = "HEAD";
long len;
using(HttpWebResponse resp = (HttpWebResponse)(req.GetResponse()))
{
len = resp.ContentLength;
}
Notice the property for the content length on the HttpWebResponse object – no need to parse the Content-Length header manually.
Note that not every server accepts HTTP HEAD requests. One alternative approach to get the file size is to make an HTTP GET call to the server requesting only a portion of the file to keep the response small and retrieve the file size from the metadata that is returned as part of the response content header.
The standard System.Net.Http.HttpClient can be used to accomplish this. The partial content is requested by setting a byte range on the request message header as:
request.Headers.Range = new RangeHeaderValue(startByte, endByte)
The server responds with a message containing the requested range as well as the entire file size. This information is returned in the response content header (response.Content.Header) with the key "Content-Range".
Here's an example of the content range in the response message content header:
{
"Key": "Content-Range",
"Value": [
"bytes 0-15/2328372"
]
}
In this example the header value implies the response contains bytes 0 to 15 (i.e., 16 bytes total) and the file is 2,328,372 bytes in its entirety.
Here's a sample implementation of this method:
public static class HttpClientExtensions
{
public static async Task<long> GetContentSizeAsync(this System.Net.Http.HttpClient client, string url)
{
using (var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url))
{
// In order to keep the response as small as possible, set the requested byte range to [0,0] (i.e., only the first byte)
request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(from: 0, to: 0);
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
if (response.StatusCode != System.Net.HttpStatusCode.PartialContent)
throw new System.Net.WebException($"expected partial content response ({System.Net.HttpStatusCode.PartialContent}), instead received: {response.StatusCode}");
var contentRange = response.Content.Headers.GetValues(#"Content-Range").Single();
var lengthString = System.Text.RegularExpressions.Regex.Match(contentRange, #"(?<=^bytes\s[0-9]+\-[0-9]+/)[0-9]+$").Value;
return long.Parse(lengthString);
}
}
}
}
WebClient webClient = new WebClient();
webClient.OpenRead("http://stackoverflow.com/robots.txt");
long totalSizeBytes= Convert.ToInt64(webClient.ResponseHeaders["Content-Length"]);
Console.WriteLine((totalSizeBytes));
HttpClient client = new HttpClient(
new HttpClientHandler() {
Proxy = null, UseProxy = false
} // removes the delay getting a response from the server, if you not use Proxy
);
public async Task<long?> GetContentSizeAsync(string url) {
using (HttpResponseMessage responce = await client.GetAsync(url))
return responce.Content.Headers.ContentLength;
}

Categories

Resources