C
C#4w ago
surwren

Refactoring Similar Network Requests

I have 3 async methods with a great deal of similarities but some differences (some use Authorization token, some have Json payload, some return Task<bool>, others Task) but all make network requests in a similar flow. What is an approach I could use to refactor them?
40 Replies
surwren
surwrenOP4w ago
async Task<bool> SendCodeRequestAsync() {
Uri fullCodeUri = new Uri(new Uri(baseUrl), codeRoute);
var registrationData = new {
loginName = emailInput.text.Trim()
};
string jsonPayload = JsonConvert.SerializeObject(registrationData);
using (HttpClient client = new HttpClient()) {
HttpContent content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");

try {
HttpResponseMessage response = await client.PostAsync(fullCodeUri, content).ConfigureAwait(false);
if (!response.IsSuccessStatusCode) {
Debug.LogError("Error from SendCodeRequestAsync(): " + response.StatusCode);
lastHttpResponseError = response;
return false;
}
//string responseContent = await response.Content.ReadAsStringAsync();
//Debug.Log("POST to Code Request API success, response: " + responseContent);
//otp_timer = OTP_DURATION;
//return true;
var responseJson = await ProcessServerResponse(response, fullCodeUri);
var responseCodeString = responseJson["code"]?.ToString();

if (int.TryParse(responseCodeString, out int responseCodeInternal) && responseCodeInternal == 200) {
otp_timer = OTP_DURATION;
return true;
}
else {
Debug.LogError($"Error - Internal status code failed during SendCodeRequestAsync(): {responseCodeInternal}");
lastHttpResponseError = response;
return false;
}
}
catch (Exception ex) {
Debug.LogError("Exception from SendCodeRequestAsync(): " + ex.Message);
return false;
}
}
}
async Task<bool> SendCodeRequestAsync() {
Uri fullCodeUri = new Uri(new Uri(baseUrl), codeRoute);
var registrationData = new {
loginName = emailInput.text.Trim()
};
string jsonPayload = JsonConvert.SerializeObject(registrationData);
using (HttpClient client = new HttpClient()) {
HttpContent content = new StringContent(jsonPayload, Encoding.UTF8, "application/json");

try {
HttpResponseMessage response = await client.PostAsync(fullCodeUri, content).ConfigureAwait(false);
if (!response.IsSuccessStatusCode) {
Debug.LogError("Error from SendCodeRequestAsync(): " + response.StatusCode);
lastHttpResponseError = response;
return false;
}
//string responseContent = await response.Content.ReadAsStringAsync();
//Debug.Log("POST to Code Request API success, response: " + responseContent);
//otp_timer = OTP_DURATION;
//return true;
var responseJson = await ProcessServerResponse(response, fullCodeUri);
var responseCodeString = responseJson["code"]?.ToString();

if (int.TryParse(responseCodeString, out int responseCodeInternal) && responseCodeInternal == 200) {
otp_timer = OTP_DURATION;
return true;
}
else {
Debug.LogError($"Error - Internal status code failed during SendCodeRequestAsync(): {responseCodeInternal}");
lastHttpResponseError = response;
return false;
}
}
catch (Exception ex) {
Debug.LogError("Exception from SendCodeRequestAsync(): " + ex.Message);
return false;
}
}
}
async Task<bool> SendLoginRequestAsync() { //Refactor with Username update request
try {
Uri fullauthUri = new Uri(new Uri(baseUrl), authRoute);
var loginData = new {
code = emailOtpInput.text.Trim(),
loginName = emailInput.text.Trim()
};
string jsonPayload = JsonConvert.SerializeObject(loginData);

using (var client = new HttpClient())
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")) {
HttpResponseMessage response = await client.PostAsync(fullauthUri, content).ConfigureAwait(false);

if (!response.IsSuccessStatusCode) {
Debug.LogError($"Error from SendLoginRequestAsync(): {response.StatusCode}");
lastHttpResponseError = response;
return false;
}
var responseJson = await ProcessServerResponse(response, fullauthUri);
var responseCodeString = responseJson["code"]?.ToString();

if (int.TryParse(responseCodeString, out int responseCodeInternal) && responseCodeInternal == 200) {
await HandleUserSessionAsync(responseJson);
//HandleUserSession(responseJson);
return true;
}
else {
Debug.LogError($"Error - Internal status code failed during SendLoginRequestAsync(): {responseCodeInternal}");
lastHttpResponseError = response;
return false;
}
}
}
catch (Exception ex) {
Debug.LogError($"Exception from SendLoginRequestAsync(): {ex.Message}");
return false;
}
}
async Task<bool> SendLoginRequestAsync() { //Refactor with Username update request
try {
Uri fullauthUri = new Uri(new Uri(baseUrl), authRoute);
var loginData = new {
code = emailOtpInput.text.Trim(),
loginName = emailInput.text.Trim()
};
string jsonPayload = JsonConvert.SerializeObject(loginData);

using (var client = new HttpClient())
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")) {
HttpResponseMessage response = await client.PostAsync(fullauthUri, content).ConfigureAwait(false);

if (!response.IsSuccessStatusCode) {
Debug.LogError($"Error from SendLoginRequestAsync(): {response.StatusCode}");
lastHttpResponseError = response;
return false;
}
var responseJson = await ProcessServerResponse(response, fullauthUri);
var responseCodeString = responseJson["code"]?.ToString();

if (int.TryParse(responseCodeString, out int responseCodeInternal) && responseCodeInternal == 200) {
await HandleUserSessionAsync(responseJson);
//HandleUserSession(responseJson);
return true;
}
else {
Debug.LogError($"Error - Internal status code failed during SendLoginRequestAsync(): {responseCodeInternal}");
lastHttpResponseError = response;
return false;
}
}
}
catch (Exception ex) {
Debug.LogError($"Exception from SendLoginRequestAsync(): {ex.Message}");
return false;
}
}
async Task SendUsernameUpdateAsync() {
if (string.IsNullOrEmpty(sessionCache.loginToken)) {
Debug.LogError("No login token found. Check...");
return;
}
Uri updateUsernameUri = new Uri(new Uri(baseUrl), updateUsernameRoute);
string jsonPayload = JsonConvert.SerializeObject(
new {
nickname = usernameInput.text.Trim(),
//signature = ""
}
);
using (HttpClient client = new HttpClient())
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")) {
try {
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", sessionCache.loginToken);
HttpResponseMessage response = await client.PostAsync(updateUsernameUri, content).ConfigureAwait(false);

if (!response.IsSuccessStatusCode) {
Debug.LogError($"Error from SendUsernameUpdateAsync(): {response.StatusCode}");
lastHttpResponseError = response;
return;
}
var responseJson = await ProcessServerResponse(response, updateUsernameUri);
var responseCodeString = responseJson["code"]?.ToString();

if (int.TryParse(responseCodeString, out int responseCodeInternal) && responseCodeInternal == 200) {
Debug.Log($"Successfully updated username ...");
return;
}
else {
Debug.LogError($"Error - Internal status code failed during SendUsernameUpdateAsync(): {responseCodeInternal}");
lastHttpResponseError = response;
return;
}
}
catch (Exception ex) {
Debug.LogError("...");
}
}
}
async Task SendUsernameUpdateAsync() {
if (string.IsNullOrEmpty(sessionCache.loginToken)) {
Debug.LogError("No login token found. Check...");
return;
}
Uri updateUsernameUri = new Uri(new Uri(baseUrl), updateUsernameRoute);
string jsonPayload = JsonConvert.SerializeObject(
new {
nickname = usernameInput.text.Trim(),
//signature = ""
}
);
using (HttpClient client = new HttpClient())
using (var content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")) {
try {
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", sessionCache.loginToken);
HttpResponseMessage response = await client.PostAsync(updateUsernameUri, content).ConfigureAwait(false);

if (!response.IsSuccessStatusCode) {
Debug.LogError($"Error from SendUsernameUpdateAsync(): {response.StatusCode}");
lastHttpResponseError = response;
return;
}
var responseJson = await ProcessServerResponse(response, updateUsernameUri);
var responseCodeString = responseJson["code"]?.ToString();

if (int.TryParse(responseCodeString, out int responseCodeInternal) && responseCodeInternal == 200) {
Debug.Log($"Successfully updated username ...");
return;
}
else {
Debug.LogError($"Error - Internal status code failed during SendUsernameUpdateAsync(): {responseCodeInternal}");
lastHttpResponseError = response;
return;
}
}
catch (Exception ex) {
Debug.LogError("...");
}
}
}
ero
ero4w ago
many issues here. what .net version are you on? is there a specific reason you use newtonsoft.json instead of system.text.json? don't create a new httpclient for every request. lots of things here are a bit overcomplicated, but we can work through them
exixt
exixt4w ago
you need to first fix the two points mentioned before refactoring any of this then get back to us
Omnissiah
Omnissiah4w ago
how much to refactor also depends from what are you building
surwren
surwrenOP4w ago
I am on .NET 2.1 I wantes to use system.text.json too How to not create a new Httpclient for every request? Do I just store it as a class variable? Which two
ero
ero4w ago
is there a reason you're using ns2.1?
exixt
exixt4w ago
not using HttpClient and not using newtonsoft either a static httpclient or httpclientfactory in heavy load you'll run into problems otherwise
surwren
surwrenOP4w ago
Pre existing project, I wish it were easy to upgrade too Its not my call
exixt
exixt4w ago
and you just dont want to using HttpClient, it's bad
surwren
surwrenOP4w ago
Ok, so I store it as a class variable and reuse it right When should I kill off the object instance or do I leave it running with the program
ero
ero4w ago
you'll have a hard time upgrading this properly on ns2.1 everything that makes this better is only accessible as a package
ero
ero4w ago
IHttpClientFactory is only really applicable if you have a proper builder to launch your app which itself is a lot of work
surwren
surwrenOP4w ago
Could you name some examples anyway? I'm keen to learn
ero
ero4w ago
for the httpclient, you'll need to decide the lifetime on your own. you could make your class implement IDisposable and dispose the client there. you can pull in the System.Net.Http.Json package for some convenience methods (pulls in system.text.json transitively)
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
ero
ero4w ago
...what makes those projects weird?
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
surwren
surwrenOP4w ago
Its aspnetcore
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
ero
ero4w ago
okay yeah then this is a really weird approach lol
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
surwren
surwrenOP4w ago
No winforms or uwp idk what those are even
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
surwren
surwrenOP4w ago
You can?
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
surwren
surwrenOP4w ago
Ok if i chose aspnetcore 6.0 what would be the next steps after that
ero
ero4w ago
to update to aspnetcore 9.0 in 4 days because 6.0 would be out of support
surwren
surwrenOP4w ago
Ok but what do I do about the httpclient and web requests lol
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
ero
ero4w ago
and like the screenshot shows, you just use SendAsJsonAsync and GetFromJsonAsync of course this will require you to have some concrete models to de/serialize say
record CodeRequest(
// or use JsonSerializerOptions with camelCase naming
[property: JsonPropertyName("loginName")] string LoginName);
record CodeRequest(
// or use JsonSerializerOptions with camelCase naming
[property: JsonPropertyName("loginName")] string LoginName);
await _client.SendAsJsonAsync(request)
surwren
surwrenOP4w ago
Oh records are a thing in c#? I'd only ever heard about them in Java Apologies, I'm not familiar with DI in .net CORE I come from Java land where we need [@Bean] or [@Resource] Spring boot How different is the configuration because this looks like DI injected HttpClient if I am not mistaken?
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
surwren
surwrenOP4w ago
I assume factory is no longer needed in this case? When would factory still be needed
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
surwren
surwrenOP4w ago
My net is dead
No description
surwren
surwrenOP4w ago
But i will definitely read it once i get back
exixt
exixt4w ago
remember we're only helping you, not bashing on your stuff we want your code better, so do you
ero
ero4w ago
i'm sceptical about how much of this actually helps if upgrading the tfm is really not their call
surwren
surwrenOP4w ago
It's ok, I want to learn I am only in this bc i wanted a progression step before seeking opportunities at a real .NET shop I am happy for all the resources, and will practice on my own even if i can't apply any of it right now Yep, no worries, sorry if I didn't reply to everything yet
Want results from more Discord servers?
Add your server