C
C#2y 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
Pobiega2y ago
Fetch the data in your controller action, send it to the view?
dond~
dond~OP2y 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
Pobiega2y ago
Have you ever made an ASP webapp before?
dond~
dond~OP2y ago
Not really
Pobiega
Pobiega2y ago
okay, so create one and use the template you want
dond~
dond~OP2y 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
Pobiega2y ago
You'll likely want either the webapp razor template, or webapp MVC literally anywhere
dond~
dond~OP2y ago
i have mvc I think
Pobiega
Pobiega2y 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~OP2y ago
I tried to add it directly in the controller but that didnt work at all
Pobiega
Pobiega2y ago
show me
dond~
dond~OP2y 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
Pobiega2y ago
uhm that code is outside the class you can't just put code anywhere you want mate
dond~
dond~OP2y ago
yea I fixed that now xD Now I have this sorry about that
Pobiega
Pobiega2y ago
There is so much wrong here
dond~
dond~OP2y ago
I guess
Pobiega
Pobiega2y ago
never use using on a HttpClient
dond~
dond~OP2y ago
eh I used it in my console app The microsoft documentation used it like that
Pobiega
Pobiega2y 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~OP2y 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
Pobiega2y ago
the best answer is to use IHttpClientFactory and inject the client but an easier solution is to use a static httpclient
dond~
dond~OP2y 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
Pobiega2y ago
yes even better would be not messing with the client defaults and instead setting that in a request message
dond~
dond~OP2y 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
Pobiega2y ago
What other languages do you know and for how long have you been coding?
dond~
dond~OP2y ago
Like a couple years now on and off, I know java python and javascript
Pobiega
Pobiega2y ago
Okay. Java is very similar to C# in how it works under the hood so the whole class/method stuff etc
dond~
dond~OP2y ago
Yea the syntax is also kinda similar which is nice
Pobiega
Pobiega2y ago
throw everything from python and JS away 😄
dond~
dond~OP2y ago
Haha yea thats a lot more simple But this company uses .NET only so I will have to get used to c#
Pobiega
Pobiega2y ago
its a very good language when you get used to it
dond~
dond~OP2y 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
Pobiega2y 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~OP2y 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
Pobiega2y 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~OP2y 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
Pobiega2y ago
you can create the model anywhere you just need to fully qualify the type in your @model line as above.
dond~
dond~OP2y 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
Pobiega2y ago
yes a model you control
dond~
dond~OP2y ago
Well GTINKeeper is a model right?
Pobiega
Pobiega2y ago
sure but s.Values isn't
dond~
dond~OP2y 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
Pobiega2y ago
what is the type definition of s.Values?
dond~
dond~OP2y ago
Ah it's a collection
Pobiega
Pobiega2y ago
ofc it is
dond~
dond~OP2y ago
which I cant pass in there I guess Can I pass a list of all the values?
Pobiega
Pobiega2y ago
you can, but perhaps turn it into a nicer type first like an array, or a List
dond~
dond~OP2y ago
yea I created a list now but that still cant be passed in the View() function I guess im missing something here
Pobiega
Pobiega2y ago
did you make your @model a list?
dond~
dond~OP2y 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
Pobiega2y ago
use ToList instead of making your own list but yeah, that should work?
dond~
dond~OP2y 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
Pobiega2y ago
ah your return type on the method is wrong it should just be Task<IActionResult>
dond~
dond~OP2y ago
Ah let me try that That worked! I can create a table with that thanks
Accord
Accord2y 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.
Want results from more Discord servers?
Add your server