Read asynchronously each line of an HTTP request - c#

I use a strange API that sends JSON objects in kind of chunks (line by line).
I need to be able to read each line of the response to my request asynchronously. I'm already trying to display in the console each of these requests.
The code below is the main one (the main{} function only calls this function). I want this code to be executed asynchronously too, that's why the function is declared as async task.
When I launch the application, the query runs fine, but the program doesn't display the lines one by one: it waits for the end of the query to display everything at once.
I'm very new to async/streams, sorry if the code is so bad.
public async Task test()
{
HttpClient client = new HttpClient();
var values = new Dictionary<string, string> // POST data
{
{ "api", "v2" },
{ "field1", "data1" },
{ "field2", "data2" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://api.domain/post", content);
using (var theStream = await response.Content.ReadAsStreamAsync())
{
StreamReader theStreamReader = new StreamReader(theStream);
string theLine = null;
while ((theLine = await theStreamReader.ReadLineAsync()) != null)
{
Console.WriteLine("----- New Line:"); //Just for the eyes
Console.WriteLine(theLine);
}
};
}

You are missing HttpCompletionOption.ResponseHeadersRead, which will only block while reading the headers, and the content comes through asynchronously. You must use SendAsync and a HttpRequestMessage for this.
Also you are missing some using blocks, and HttpClient should be cached in a static field.
static HttpClient _client = new HttpClient();
public async Task test()
{
var values = new Dictionary<string, string> // POST data
{
{ "api", "v2" },
{ "field1", "data1" },
{ "field2", "data2" }
};
using (var content = new FormUrlEncodedContent(values))
using (var request = new HttpRequestMessage(HttpMethod.Post, "http://api.domain/post"){ Content = content })
using (var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
using (var theStream = await response.Content.ReadAsStreamAsync())
using (var theStreamReader = new StreamReader(theStream))
{
string theLine = null;
while ((theLine = await theStreamReader.ReadLineAsync()) != null)
{
Console.WriteLine("----- New Line:"); //Just for the eyes
Console.WriteLine(theLine);
}
};
}

Related

Simple Post and Get C# WPF

I have two textboxes and a button. I want to put something in textBox1, send that to a server and put the results I get back in textBox2.
I can't seem to understand sockets well enough to accomplish this. I have an address and a port.
Does anyone have just a super simple setup to do this? Everything I've found includes classes I can't even find namespaces for.
Thanks!
Here is a simple solution to get data from a website:
private static HttpClient _client = new HttpClient();
public static async Task<string> GetWebsiteDataAsync(Uri fromUri)
{
using (var msg = new HttpRequestMessage(HttpMethod.Get, fromUri))
using (var resp = await _client.SendAsync(msg))
{
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
}
You would then call it as so:
var websiteData = await GetWebsiteDataAsync(new Uri("https://example.com"));
Your title asked for Post as well, so here's how you'd do that (requires Newtonsoft.Json nuget package):
public static async Task<TResult> PostObjectToWebsiteAsync<TResult>(
Uri site, object objToPost)
{
using (var req = new HttpRequestMessage(HttpMethod.Post, site))
{
req.Content = new StringContent(JsonConvert.SerializeObject(objToPost),
Encoding.UTF8, "application/json");
using (var resp = await _client.SendAsync(req))
{
resp.EnsureSuccessStatusCode();
using (var s = await resp.Content.ReadAsStreamAsync())
using (var sr = new StreamReader(s))
using (var jtr = new JsonTextReader(sr))
{
return new JsonSerializer().Deserialize<TResult>(jtr);
}
}
}
}
And you could call that like this:
var objToPost = new
{
hello = "world",
value = 5
}
var postResonse = await PostObjectToWebsiteAsync<object>(
new Uri("https://example.com"), objToPost);

how to get API response it in asp.net c#

i have the following API json request
"myjsonrequest": {
"ServiceKey": "Hello",
"Identityvals": {
"IDName": "regnum",
"IDValue": "112233"
}
}
any simple way to get the response , im using ASP.net c#
i tried this code
HttpClient client = new HttpClient();
string x = "{'IDName','regnum'},{'IDValue','112233'}";
var Keys = new Dictionary<string, string>
{
{ "ServiceKey", "hello" },
{ "PractitionerIdentity",x}
};
var content = new FormUrlEncodedContent(Keys);
var response = await client.PostAsync("https://apiurl", content);
var responseval = await response.Content.ReadAsStringAsync();
Try this :
var json = new {
ServiceKey = "",
PractitionerIdentity = new {
IDName = "" ,
IDValue = ""
}
};
HttpClient client = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json")
var response = await client.PostAsync("https://apiurl", content);
Your Json data should be saved to a model in the following way:
public class YourJsonData{
public string ServiceKey {get; set;}
//add other names
}
The best thing about this is that if you call your object, you get a variable back for easy usage.
then you can add it in a task:
public async Task<List<YourJsonData>> GetJsonAsync(CancellationToken cancellationToken = default)
{
using (var client = new HttpClient())
{
//Make the request, and ensure we can reach it
var response = await client.GetAsync(yourJosnUrl, cancellationToken);
if (response.IsSuccessStatusCode)
{
//Read the actual stream (download the content)
var content = await response.Content.ReadAsStringAsync();
//Make sure we do have some valid content before we try to deserialize it
if (string.IsNullOrEmpty(content))
{
return new List<YourJsonData>();
}
//Deserialize into a list of yourjsondata
return JsonConvert.DeserializeObject<List<YourJsonData>>(content);
}
}
return new List<YourJsonData>();
}
also if you are lazy, you can replace YourJsonData with dynamic. the downpart here is that you won't be able to see what you are revering to.

Xamarin Sending POST Data

I am attempting to send POST data to my server and get back a response. For some reason, no POST data is actually getting sent. A request is being sent to my server but the POST array is empty.
Here is my code for sending the request:
public class GlobalMethods
{
public async Task<string> callAjax(string mthd,NameValueCollection parameters)
{
var client = new HttpClient();
var content = JsonConvert.SerializeObject(parameters);
var result = await client.PostAsync("http://dev.adex-intl.com/adex/mvc/receiving/"+mthd, new StringContent(content)).ConfigureAwait(false);
var tokenJson = "";
if (result.IsSuccessStatusCode)
{
tokenJson = await result.Content.ReadAsStringAsync();
}
return tokenJson;
}
}
And here is my code that calls the above method:
public void loginPressed(object sender, EventArgs e)
{
if(String.IsNullOrEmpty(badge.Text)) {
DisplayAlert("Error", "Enter your badge number", "Ok");
} else {
IsBusy = true;
NameValueCollection parameters = new NameValueCollection();
parameters["badgetNumber"] = badge.Text;
GlobalMethods globalMethods = new GlobalMethods();
var results = globalMethods.callAjax("login", parameters);
}
}
I'm not sure what I'm doing wrong. Also, I'm a newbie to Xamarin and C# so I'm not even sure if the way I am attempting to do things is the best way.
You haven't specify the type of content that you want to send, in your case it's 'application/json', you can set it like that:
"var client = new HttpClient();
var content = new StringContent(JsonConvert.SerializeObject(parameters));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");". Also, I would suggest you to write code like that:
var uri = new Uri(url);
using (var body = new StringContent(JsonConvert.SerializeObject(data)))
{
body.Headers.ContentType = new MediaTypeHeaderValue("application/json");
var request = new HttpRequestMessage
{
Version = new Version(1, 0),
Content = body,
Method = HttpMethod.Post,
RequestUri = uri
};
try
{
using (var response = await _client.SendAsync(request,cancellationToken))
{
if (response.IsSuccessStatusCode)
{
//Deal with success response
}
else
{
//Deal with non-success response
}
}
}
catch(Exception ex)
{
//Deal with exception.
}
}
You can use PostAsync for async sending data to server. your code should be something like this:
HttpClient client = new HttpClient();
var values = new Dictionary<string, string>
{
{ "p1", "data1" },
{ "p2", "data2" }
};
var content = new FormUrlEncodedContent(values);
var response = await client.PostAsync("http://www.example.com/index.php", content);
var responseString = await response.Content.ReadAsStringAsync();

How to implement a multipart post request in c# wp8.1 (winrt)

Already second day trying to implement a multipart post request, but so far I have failed.
Task: to send 1 or 2 pictures to the server.
Please tell me how to do this in Windows Phone 8.1 (WinRT). Already tried a huge number of links on the Internet, but nothing happened.
p.s. in the description of the API server written that you must submit a request in the following format.
{
"type": "object",
"properties": {
"files": {
"type": "array",
"items": {
"type": "file"
}
}
}
}
Yes, of course. Here is my code. I searched the Internet and eventually tried to implement this. Interestingly, it worked and sent the data to the server. only the North returned the error: "data error", so I sent out in the wrong format. I assume it's because not json created structure, about which I wrote above.
public async static Task<bool> UploadFiles(StorageFile file)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
System.Net.Http.HttpClient httpClient = new System.Net.Http.HttpClient();
System.Net.Http.MultipartFormDataContent form = new System.Net.Http.MultipartFormDataContent();
form.Add(new System.Net.Http.StringContent(UserLogin), "username");
form.Add(new System.Net.Http.StringContent(UserPassword), "password");
form.Add(new System.Net.Http.ByteArrayContent(bytes, 0, bytes.Length), "files", "items");
form.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
System.Net.Http.HttpResponseMessage response = await httpClient.PostAsync(UploadFilesURI, form);
response.EnsureSuccessStatusCode();
httpClient.Dispose();
string sd = response.Content.ReadAsStringAsync().Result;
return true;
}
Sorry for this style of code. Haven't quite figured out how to insert it correctly in the posts
I eventually solved my problem. The code give below
public async static Task<string> UploadFiles(StorageFile[] files)
{
try
{
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
client.DefaultRequestHeaders.AcceptLanguage.Add(new StringWithQualityHeaderValue("ru"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", "token=" + SessionToken);
var content = new System.Net.Http.MultipartFormDataContent();
foreach (var file in files)
{
if (file != null)
{
var streamData = await file.OpenReadAsync();
var bytes = new byte[streamData.Size];
using (var dataReader = new DataReader(streamData))
{
await dataReader.LoadAsync((uint)streamData.Size);
dataReader.ReadBytes(bytes);
}
string fileToUpload = file.Path;
using (var fstream = await file.OpenReadAsync())
{
var streamContent = new System.Net.Http.ByteArrayContent(bytes);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "files[]",
FileName = Path.GetFileName(fileToUpload),
};
content.Add(streamContent);
}
}
}
var response = await client.PostAsync(new Uri(UploadFilesURI, UriKind.Absolute), content);
var contentResponce = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<API.ResponceUploadFiles.RootObject>(contentResponce);
return result.cache;
}
catch { return ""; }
}

C# HttpClient POST request

i'm trying to create a POST request and I can't get it to work.
this is the format of the request which has 3 params, accountidentifier / type / seriesid
http://someSite.com/api/User_Favorites.php?accountid=accountidentifier&type=type&seriesid=seriesid
and this is my C#
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri("http://somesite.com");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("accountidentifier", accountID),
new KeyValuePair<string, string>("type", "add"),
new KeyValuePair<string, string>("seriesid", seriesId),
});
httpClient.PostAsync("/api/User_Favorites.php", content);
}
Any ideas?
IMO, dictionaries in C# are very useful for this kind of task.
Here is an example of an async method to complete a wonderful POST request:
public class YourFavoriteClassOfAllTime {
//HttpClient should be instancied once and not be disposed
private static readonly HttpClient client = new HttpClient();
public async void Post()
{
var values = new Dictionary<string, string>
{
{ "accountidentifier", "Data you want to send at account field" },
{ "type", "Data you want to send at type field"},
{ "seriesid", "The data you went to send at seriesid field"
}
};
//form "postable object" if that makes any sense
var content = new FormUrlEncodedContent(values);
//POST the object to the specified URI
var response = await client.PostAsync("http://127.0.0.1/api/User_Favorites.php", content);
//Read back the answer from server
var responseString = await response.Content.ReadAsStringAsync();
}
}
You can try WebClient too. It tries to accurately simulate what a browser would do:
var uri = new Uri("http://whatever/");
WebClient client = new WebClient();
var collection = new Dictionary<string, string>();
collection.Add("accountID", accountID );
collection.Add("someKey", "someValue");
var s = client.UploadValuesAsync(uri, collection);
Where UploadValuesAsync POSTs your collection.

Categories

Resources