Several Ways To Send Request And Get Response Via HttpClient
Like I mentioned before, using HttpClient is a large nad important subject in many programming languages.
Therefore, let's talk about that how to send requests through HttpClient. Think about it, the easiest request: In our system, how can we grab data from a remote service? Such as Weathers, Financial information. And how to do that ?
Workshop
Here are some examples about sending requests, getting response via HttpClient.
In many situations, working on HttpClient with System.Net.Http.Json, will have a great help.
-Basic HttpGet
try
{
const string url = "https://jsonplaceholder.typicode.com/posts";
Console.WriteLine($"== result ==\n");
var result = httpClient.GetAsync(url).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
Console.WriteLine(result+"\n\n");
Console.WriteLine($"== result 2 ==\n");
// the result is same as result2 with few different calling
var result2 = httpClient.GetStringAsync(url).GetAwaiter().GetResult();
Console.WriteLine(result2 + "\n\n");
Console.WriteLine($"== result 3 ==\n");
// deserialize result2 string into IEnumerable<Pdata> strong type object
var result3 = System.Text.Json.JsonSerializer.Deserialize<IEnumerable<Pdata>>(result2);
foreach(var item in result3)
{
Console.WriteLine($"{item?.Id}, {item?.UserId}, {item?.Title}, {item?.Body}\n\n");
}
Console.WriteLine($"== result 4 ==\n");
// result4 is same as result3, but using an easier way with System.Net.Http.Json extension.
var result4 = httpClient.GetFromJsonAsync<IEnumerable<Pdata>>(url).GetAwaiter().GetResult();
foreach (var item in result4)
{
Console.WriteLine($"{item?.Id}, {item?.UserId}, {item?.Title}, {item?.Body}\n\n");
}
Console.WriteLine($"== result 5 ==\n");
// result5 is a standard way to send request, it can help us to fully control about HttpRequest, HttpResponse
var req = new HttpRequestMessage(HttpMethod.Get, url);
var sendReq = _httpClient.SendAsync(req).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
var result5 = System.Text.Json.JsonSerializer.Deserialize<IEnumerable<Pdata>>(sendReq);
foreach (var item in result5)
{
Console.WriteLine($"{item?.Id}, {item?.UserId}, {item?.Title}, {item?.Body}\n\n");
}
}
catch
{
throw;
}
The result is same as result2 with few different calling.
The result3 is deserializing result2 (or result) string into IEnumerable<Pdata>, a strong type object.
The result4 is same as result3, but using an easier way with System.Net.Http.Json extension.
The result5 is a standard way to send request, it can help us to fully control about HttpRequest, HttpResponse.
Result, Basic HttpGet
-HttpGet with Authorization Bearer token
try
{
const string url = "https://api.spotify.com/v1/me/playlists";
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_SPOYIFY_AUTHORIZATION_TOKEN");
var playlist = _httpClient.GetFromJsonAsync<ObjectPagingList<Playlist>>(url).GetAwaiter().GetResult();
...
}
catch
{
throw;
}
Calling api with Bearer Token.
Result, HttpGet with Authorization Bearer token
-HttpPost Json Data to Create
try
{
const string url = "https://jsonplaceholder.typicode.com/posts";
var data = new Pdata
{
Title = "foo",
Body = "bar",
UserId = 1991
};
// while sending Json data to api, don't forget to set up content-type.
// if not, we might get 405 Method Not Allowed, or wrong data deliveried.
//_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//_httpClient.DefaultRequestHeaders.Accept.TryParseAdd("application/json");
// or setting it up directly in StringContent
var jstr = _httpClient.PostAsync(url,
new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json")
).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
var pdata = JsonSerializer.Deserialize<Pdata>(jstr);
// or we can easily called ReadFromJsonAsync function supported by System.Net.Http.Json extension
//var pdata = _httpClient.PostAsJsonAsync(url, data).GetAwaiter().GetResult().Content.ReadFromJsonAsync<Pdata>().GetAwaiter().GetResult();
...
}
catch
{
throw;
}
While sending Json data to api, don't forget to set up content-type. If not, we might get 405 Method Not Allowed, or wrong data delivered.
HttpPost Json Data to Create while Wrong Content-Type Setting
Result, HttpPost Json Data to Create
-HttpPost by Form (default to enctype="application/x-www-form-urlencoded")
var tokenUrl = "https://accounts.spotify.com/api/token";
var req = new HttpRequestMessage(HttpMethod.Post, tokenUrl) {
Content = new FormUrlEncodedContent(new Dictionary<string, string> {
{ "grant_type", "authorization_code" },
{ "code", code },
{ "redirect_uri", "_YOUR_CALLBACK_URL_" },
}),
};
try
{
httpClient.DefaultRequestHeaders.Add("Authorization", $"Basic {_YOUR_BASIC_AUTHORIZATION_}");
var sendReq = _httpClient.SendAsync(req).GetAwaiter().GetResult();
if (sendReq.IsSuccessStatusCode)
{
var json = sendReq.Content.ReadAsStringAsync().GetAwaiter().GetResult();
var pdata = JsonSerializer.Deserialize<TokenData>(json);
...
}
return default;
}
catch
{
throw;
}
Aka standard Form Submit, a common way of sending data.
Result, HttpPost by Form (default to enctype="application/x-www-form-urlencoded")
-HttpPost An Image File by multipart/form-data
try
{
using var stream = new FileStream(@"r:\animage.jpg", FileMode.Open);
var streamContent = new StreamContent(stream);
streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{
Name = "image",
FileName = "animage.jpg"
};
const string url = "https://api.imgur.com/3/image";
var req = new HttpRequestMessage(HttpMethod.Post, url) {
Content = new MultipartFormDataContent
{
{ streamContent, "image", "animage.jpg" },
// based on imgur api, add more fields to post
{ new StringContent("file"), "type" },
{ new StringContent("animage.jpg"), "name" },
{ new StringContent("an image upload test"), "title" },
{ new StringContent("a description"), "description" }
}
};
_httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_IMGUR_AUTHORIZATION_TOKEN");
var sendReq = _httpClient.SendAsync(req).GetAwaiter().GetResult();
//var sendReq2 = _httpClient.PostAsync(url, multipartFormDataContent).GetAwaiter().GetResult();
...
}
catch
{
throw;
}
An other important, and more useful way of sending data to an api.
Result, HttpPost An Image File by multipart/form-data
-HttpPut Request
try
{
const string url = "https://jsonplaceholder.typicode.com/posts/1";
var data = new Pdata
{
Title = "foo-1",
Body = "bar-1",
Id = 1
};
var res = _httpClient.PutAsync(url,
new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json")
).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
...
}
catch
{
throw;
}
Result, HttpPut Request
-HttpPatch Request
try
{
const string url = "https://jsonplaceholder.typicode.com/posts/1";
var data = new Pdata
{
Title = "foo-2",
Body = "bar-2",
Id = 1
};
var jstr = _httpClient.PatchAsync(url,
new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json")
).GetAwaiter().GetResult().Content.ReadAsStringAsync().GetAwaiter().GetResult();
...
}
catch
{
throw;
}
Result, HttpPatch Request
And, that's it. These're almost all kinds of sending and grabbing operations through the HttpClient.
Enjoy it.
References:
Make HTTP requests using IHttpClientFactory in ASP.NET Core
使用者驗證與授權 - Token Based Authentication:驗證 JSON Web Token
C# HttpClient WebAPI : 6. 使用 POST 要求與 multipart/form-data MIME 類型編碼內容 呼叫 Web API
.NET 非同步程式小技巧:GetAwaiter().GetResult() 與 Result 的差異