C
C#7mo ago
Brutal_Boost

Is there a way to get rid of the Task type on an object?

I am building my first full stack app where I am building a .NET core website and an API for it to make queries to the database. I am having trouble converting the API returns into the proper formats that I need for the front end. I can't figure out how to convert Task<IEnumerable<Appetizer>> into List<Appetizer>. I've tried a few different solutions and no luck so far.
public class AppetizerService
{
private List<Appetizer> appetizers = new List<Appetizer>();

public static string BaseAddress = "http://127.0.0.1:5000";
static readonly string Url = $"{BaseAddress}/";

static HttpClient client = new HttpClient();

public async Task InitializeAppetizerServiceAsync()
{
this.appetizers = getAppetizers();
await Task.Delay(100);
}

public List<Appetizer> getAppetizers()
{
this.appetizers = getAllAppsFromApi();

return this.appetizers;
}


public static async Task<IEnumerable<Appetizer>> getAllAppsFromApi()
{

string result = await client.GetStringAsync($"{Url}api/all_apps");

var temp = JsonConvert.DeserializeObject<List<Appetizer>>(result);

return temp;

}
}
public class AppetizerService
{
private List<Appetizer> appetizers = new List<Appetizer>();

public static string BaseAddress = "http://127.0.0.1:5000";
static readonly string Url = $"{BaseAddress}/";

static HttpClient client = new HttpClient();

public async Task InitializeAppetizerServiceAsync()
{
this.appetizers = getAppetizers();
await Task.Delay(100);
}

public List<Appetizer> getAppetizers()
{
this.appetizers = getAllAppsFromApi();

return this.appetizers;
}


public static async Task<IEnumerable<Appetizer>> getAllAppsFromApi()
{

string result = await client.GetStringAsync($"{Url}api/all_apps");

var temp = JsonConvert.DeserializeObject<List<Appetizer>>(result);

return temp;

}
}
14 Replies
mg
mg7mo ago
Is the getAllAppsFromApi method even compiling? DeserializeObject doesn't return a Task
Angius
Angius7mo ago
Step one: Tasks should be awaited No exceptions Also, why use Newtonsoft? JSON serialization just comes with the framework nowadays Also also, method names are PascalCase not camelCase
mg
mg7mo ago
totally forgot entirely how async methods work whoops But yeah, await a Task to get its result
Thinker
Thinker7mo ago
Also don't create an HttpClient inside the service, inject an IHttpClientFactory into the service
Brutal_Boost
Brutal_Boost7mo ago
Yeah I just learned about the clientfactory now and once I get this working I am going to implement that. I've tried doing
this.appetizers = await getAllAppsFromApi();
this.appetizers = await getAllAppsFromApi();
and it errors within the getAppetizers() method (will change the method names to pascal case also). I'm guessing getAppetizers() needs to be async as well?
Angius
Angius7mo ago
1. If a method awaits anything, it has to be async 2. If a method is async it has to return Task or Task<T> 3. If a method is async it has to be awaited Them's the rules So, yes, the GetAppetizers method has to be async as well And has to return Task<LIst<Appetizer>>
Brutal_Boost
Brutal_Boost7mo ago
How does this look outside of not using IHttpClientFactory:
using System.Security.Cryptography.X509Certificates;
using AppChallenge.Entities;
using Newtonsoft.Json;
using System.Linq;

namespace AppChallenge.Services
{
public class AppetizerService
{
private List<Appetizer> appetizers = new List<Appetizer>();

public static string BaseAddress = "http://127.0.0.1:5000";
static readonly string Url = $"{BaseAddress}/";

static HttpClient client = new HttpClient();

public async Task InitializeAppetizerServiceAsync()
{
GetAppetizers();

await Task.Delay(100);
}

public List<Appetizer> GetAppetizerList()
{
GetAppetizers();
return this.appetizers;
}

public async Task GetAppetizers()
{

var temp = await GetAllAppsFromApi();

this.appetizers = temp.ToList();
}

public static async Task<List<Appetizer>> GetAllAppsFromApi()
{
string result = await client.GetStringAsync($"{Url}api/all_apps");

return JsonConvert.DeserializeObject<List<Appetizer>>(result);
}

}
}
using System.Security.Cryptography.X509Certificates;
using AppChallenge.Entities;
using Newtonsoft.Json;
using System.Linq;

namespace AppChallenge.Services
{
public class AppetizerService
{
private List<Appetizer> appetizers = new List<Appetizer>();

public static string BaseAddress = "http://127.0.0.1:5000";
static readonly string Url = $"{BaseAddress}/";

static HttpClient client = new HttpClient();

public async Task InitializeAppetizerServiceAsync()
{
GetAppetizers();

await Task.Delay(100);
}

public List<Appetizer> GetAppetizerList()
{
GetAppetizers();
return this.appetizers;
}

public async Task GetAppetizers()
{

var temp = await GetAllAppsFromApi();

this.appetizers = temp.ToList();
}

public static async Task<List<Appetizer>> GetAllAppsFromApi()
{
string result = await client.GetStringAsync($"{Url}api/all_apps");

return JsonConvert.DeserializeObject<List<Appetizer>>(result);
}

}
}
GetAppetizerList is what is called externally.
Angius
Angius7mo ago
I don't see you awaiting GetAppetizers()
Brutal_Boost
Brutal_Boost7mo ago
So even if you don't return anything it still needs awaited?
Angius
Angius7mo ago
Yes
MODiX
MODiX7mo ago
Angius
1. If a method awaits anything, it has to be async 2. If a method is async it has to return Task or Task<T> 3. If a method is async it has to be awaited
React with ❌ to remove this embed.
Angius
Angius7mo ago
Also, it doesn't not return anything It returns a Task And a Task has to be awaited
Brutal_Boost
Brutal_Boost7mo ago
I guess I am struggling with how to go about getting it into list form for the front end. I went ahead and added the front end where I am trying to display the list. Basically I want to populate
List<Appetizer> appetizers = new List<Appetizer>();
List<Appetizer> appetizers = new List<Appetizer>();
with what the API returns.
@page "/appetizerlist"
@using AppChallenge.Entities
@using AppChallenge.Services
@inject AppetizerService appetizerService
@inject UserService userService

<PageTitle>AppetizerList</PageTitle>

<h3>AppetizerList</h3>


@foreach (var app in appetizers)
{
<p>
<h3><a href="/appetizerDetails?appetizer=@app.get_ID()}">@app.get_name()</a> </h3>
<p>@app.get_description()</p>
<h3>@userService.get_user(@app.get_user()).get_FirstName()</h3>
</p>
}

@code {

List<Appetizer> appetizers = new List<Appetizer>();

protected override void OnInitialized()
{
appetizers = appetizerService.GetAppetizerList();

}

}
@page "/appetizerlist"
@using AppChallenge.Entities
@using AppChallenge.Services
@inject AppetizerService appetizerService
@inject UserService userService

<PageTitle>AppetizerList</PageTitle>

<h3>AppetizerList</h3>


@foreach (var app in appetizers)
{
<p>
<h3><a href="/appetizerDetails?appetizer=@app.get_ID()}">@app.get_name()</a> </h3>
<p>@app.get_description()</p>
<h3>@userService.get_user(@app.get_user()).get_FirstName()</h3>
</p>
}

@code {

List<Appetizer> appetizers = new List<Appetizer>();

protected override void OnInitialized()
{
appetizers = appetizerService.GetAppetizerList();

}

}
Angius
Angius7mo ago
GetAppetizerList is asynchronous So it needs to be awaited You can use OnInitializedAsync()