C
C#13mo ago
dond~

❔ Call an API, get information and then display it on an ASP.NET app

hello, I have created a console application that can retrieve data from an API. Now I want to display this data on an ASP.NET webapp, but I can't find anything on how to do this. Can anyone help me get started?
55 Replies
Pobiega
Pobiega13mo ago
Fetch the data in your controller action, send it to the view?
dond~
dond~13mo ago
Yes, but I dont know how to do that and I am not sure where to get started I cant find anything on the web
Pobiega
Pobiega13mo ago
Have you ever made an ASP webapp before?
dond~
dond~13mo ago
Not really
Pobiega
Pobiega13mo ago
okay, so create one and use the template you want
dond~
dond~13mo ago
I've gone ahead and looked at the basics of making the asp webapp using visual studio code The thing I am struggling with is, is where to put the async task of retrieving the results and then how to display the results
Pobiega
Pobiega13mo ago
You'll likely want either the webapp razor template, or webapp MVC literally anywhere
dond~
dond~13mo ago
i have mvc I think
Pobiega
Pobiega13mo ago
you can make a service class and register that with your DI, or add it directly in the controller to display the values, you call that method in your controller action and pass the data into your view
dond~
dond~13mo ago
I tried to add it directly in the controller but that didnt work at all
Pobiega
Pobiega13mo ago
show me
dond~
dond~13mo ago
One sec Okay so I have this Controller class
namespace ASPWebApp.Controllers;


public class HomeController : Controller
{
static async Task GetTopProduct(HttpClient client)
{
//Code to get the string I want
return string;
}
public async string Index(){
using HttpClient client = new();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
string s = await GetTopProduct(client);
}
}
namespace ASPWebApp.Controllers;


public class HomeController : Controller
{
static async Task GetTopProduct(HttpClient client)
{
//Code to get the string I want
return string;
}
public async string Index(){
using HttpClient client = new();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
string s = await GetTopProduct(client);
}
}
It doesnt like me creating a HTTPClient and then it also doesnt recognize the variable
Pobiega
Pobiega13mo ago
uhm that code is outside the class you can't just put code anywhere you want mate
dond~
dond~13mo ago
yea I fixed that now xD Now I have this sorry about that
Pobiega
Pobiega13mo ago
There is so much wrong here
dond~
dond~13mo ago
I guess
Pobiega
Pobiega13mo ago
never use using on a HttpClient
dond~
dond~13mo ago
eh I used it in my console app The microsoft documentation used it like that
Pobiega
Pobiega13mo ago
no they don't they actively say you should not
HttpClient is intended to be instantiated once and reused throughout the life of an application.
also, you can't just slap async on a method you need to change the returntype to async Task<string> and GetTopProduct also needs to return Task<string>
dond~
dond~13mo ago
okay okay I fixed that It works omg haha So I should define my HTTPClient in the Index() function? Or is that a bad idea still
Pobiega
Pobiega13mo ago
the best answer is to use IHttpClientFactory and inject the client but an easier solution is to use a static httpclient
dond~
dond~13mo ago
public static HttpClient client = new();

public async Task<string> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
string s = await GetTopProduct(client);
return s;
}
public static HttpClient client = new();

public async Task<string> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
string s = await GetTopProduct(client);
return s;
}
So this is better then?
Pobiega
Pobiega13mo ago
yes even better would be not messing with the client defaults and instead setting that in a request message
dond~
dond~13mo ago
Ah okay Thank you so much, sorry about my cursed code I started with c# two days ago for a job interview xD
Pobiega
Pobiega13mo ago
What other languages do you know and for how long have you been coding?
dond~
dond~13mo ago
Like a couple years now on and off, I know java python and javascript
Pobiega
Pobiega13mo ago
Okay. Java is very similar to C# in how it works under the hood so the whole class/method stuff etc
dond~
dond~13mo ago
Yea the syntax is also kinda similar which is nice
Pobiega
Pobiega13mo ago
throw everything from python and JS away 😄
dond~
dond~13mo ago
Haha yea thats a lot more simple But this company uses .NET only so I will have to get used to c#
Pobiega
Pobiega13mo ago
its a very good language when you get used to it
dond~
dond~13mo ago
Yea its used a lot I heard Can I print an HTML table at this return line too?
public async Task<string> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
string s = await GetTopProduct(client);
return s;
}
public async Task<string> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
string s = await GetTopProduct(client);
return s;
}
Pobiega
Pobiega13mo ago
uhm use a view if this is MVC, you'd return View(yourViewModel); where yourViewModel is just a POCO that contains all the data you want to display
dond~
dond~13mo ago
@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
And then I change this so that it displays the table?
Pobiega
Pobiega13mo ago
@model TestingMVC.Models.Home.HomeIndexModel

@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<ul>
@foreach (var name in Model.Pokemons)
{
<li>@name</li>
}
</ul>
</div>
@model TestingMVC.Models.Home.HomeIndexModel

@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<ul>
@foreach (var name in Model.Pokemons)
{
<li>@name</li>
}
</ul>
</div>
something like this
dond~
dond~13mo ago
ahhhh okay I think I get it and then I create the model in the models folder right? Because for some reason it cant find my model
Pobiega
Pobiega13mo ago
you can create the model anywhere you just need to fully qualify the type in your @model line as above.
dond~
dond~13mo ago
Ooh I need to specify the object there I got it I put the whole file xD Hmm, I wrote this now
public async Task<Dictionary<string, GTINKeeper>> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
Dictionary<string, GTINKeeper> s = await GetTopProduct(client);
return View(s.Values);
}
public async Task<Dictionary<string, GTINKeeper>> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
Dictionary<string, GTINKeeper> s = await GetTopProduct(client);
return View(s.Values);
}
But I cant pass s.Values in the View, should I convert it to some different object?
Pobiega
Pobiega13mo ago
yes a model you control
dond~
dond~13mo ago
Well GTINKeeper is a model right?
Pobiega
Pobiega13mo ago
sure but s.Values isn't
dond~
dond~13mo ago
public class GTINKeeper
{
public GTINKeeper(string? gtin, int quantity, string? name)
{
GTIN = gtin;
Quantity = quantity;
Name = name;
}

public string? GTIN { get; set; }
public int Quantity { get; set; }
public string? Name { get; set; }
}
public class GTINKeeper
{
public GTINKeeper(string? gtin, int quantity, string? name)
{
GTIN = gtin;
Quantity = quantity;
Name = name;
}

public string? GTIN { get; set; }
public int Quantity { get; set; }
public string? Name { get; set; }
}
I defined it like this Isn't s.Values a list of all the GTINKeepers?
Pobiega
Pobiega13mo ago
what is the type definition of s.Values?
dond~
dond~13mo ago
Ah it's a collection
Pobiega
Pobiega13mo ago
ofc it is
dond~
dond~13mo ago
which I cant pass in there I guess Can I pass a list of all the values?
Pobiega
Pobiega13mo ago
you can, but perhaps turn it into a nicer type first like an array, or a List
dond~
dond~13mo ago
yea I created a list now but that still cant be passed in the View() function I guess im missing something here
Pobiega
Pobiega13mo ago
did you make your @model a list?
dond~
dond~13mo ago
No I did not its a single object but now I did Still doesnt work though
@model List<ASPWebApp.Models.GTINKeeper>;

@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<ul>
@foreach(var content in Model)
{
<li>@content.Name</li>
}
</ul>
@model List<ASPWebApp.Models.GTINKeeper>;

@{
ViewData["Title"] = "Home Page";
}

<div class="text-center">
<h1 class="display-4">Welcome</h1>
<ul>
@foreach(var content in Model)
{
<li>@content.Name</li>
}
</ul>
public async Task<Dictionary<string, GTINKeeper>> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
Dictionary<string, GTINKeeper> s = await GetTopProduct(client);
List<GTINKeeper> GTINKeepers = new List<GTINKeeper>();
foreach(var item in s){
GTINKeepers.Add(item.Value);
}
return View(GTINKeepers);
}
public async Task<Dictionary<string, GTINKeeper>> IndexAsync(){
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json-patch+json"));
client.DefaultRequestHeaders.Add("User-Agent", ".NET Foundation Repository Reporter");
Dictionary<string, GTINKeeper> s = await GetTopProduct(client);
List<GTINKeeper> GTINKeepers = new List<GTINKeeper>();
foreach(var item in s){
GTINKeepers.Add(item.Value);
}
return View(GTINKeepers);
}
Got these 2 now
Pobiega
Pobiega13mo ago
use ToList instead of making your own list but yeah, that should work?
dond~
dond~13mo ago
s.Values.ToList()
s.Values.ToList()
This? Because that doesnt do it either
Cannot implicitly convert type 'Microsoft.AspNetCore.Mvc.ViewResult' to 'System.Collections.Generic.Dictionary<string, ASPWebApp.Models.GTINKeeper>' [ASPWebApp]
Cannot implicitly convert type 'Microsoft.AspNetCore.Mvc.ViewResult' to 'System.Collections.Generic.Dictionary<string, ASPWebApp.Models.GTINKeeper>' [ASPWebApp]
Pobiega
Pobiega13mo ago
ah your return type on the method is wrong it should just be Task<IActionResult>
dond~
dond~13mo ago
Ah let me try that That worked! I can create a table with that thanks
Accord
Accord13mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.