C
C#2y ago
júlio

❔ Web Services - Beginner

Hello, I'm in the process of learning Web Services. I have successfully followed the tutorial (https://learn.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-7.0&tabs=visual-studio) and had it running, and everything works fine. I would now like to explore a bit more with Web Services. My first question is the following:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();
This is the default code that comes with the Program.cs file when I create a new ASP.NET Core Empty Project. If in my browser I do localhost.../ I will get Hello World!. My goal is to be able to pass and interpret parameters now. What changes to the code would I have to make, If I wanted to check if the parameter, for example name was passed, so that the code now does Hello <name>!?
Tutorial: Create a minimal API with ASP.NET Core
Learn how to build a minimal API with ASP.NET Core.
172 Replies
júlio
júlioOP2y ago
This is what I think I would need to do:
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/{name}", (String name) => "Hello {name}!");

app.Run();
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/{name}", (String name) => "Hello {name}!");

app.Run();
Pobiega
Pobiega2y ago
$tias
Pobiega
Pobiega2y ago
but yeah, that looks about right
júlio
júlioOP2y ago
Well I did 😅 And I'm not sure I got the hand of the parameter thing Hello {name}! This is the output app.MapGet("/{name}", (String name) => "Hello {name}!");
Pobiega
Pobiega2y ago
ah you missed a $
júlio
júlioOP2y ago
This is the code Oh right
Pobiega
Pobiega2y ago
also, prefer the string type over String they are the same, but the string can't be changed by scope its just convention to use the lowercase alias 🙂
júlio
júlioOP2y ago
Noted So, for multiple parameters, I would repeat the pattern?
FusedQyou
FusedQyou2y ago
Yes
Pobiega
Pobiega2y ago
More or less. Http parameters can come in a few different forms
FusedQyou
FusedQyou2y ago
You can also inject services, might be a nice topic to look up
Pobiega
Pobiega2y ago
what you have right now is a "route parameter"
FusedQyou
FusedQyou2y ago
Really depends on the context but you can pass a lot. Query parameters, route parameters, body objects, services
Pobiega
Pobiega2y ago
http://localhost/Steve will print "Hello Steve"
FusedQyou
FusedQyou2y ago
You can also split the method you made into its own controller which could be more scalable and easier
Pobiega
Pobiega2y ago
query parameters look like this: http://localhost/?name=Steve&age=28
júlio
júlioOP2y ago
The end goal would be to do something like website/name=wasd&age=5&address=Something
Pobiega
Pobiega2y ago
and then you can also have your request submit a payload (aka request body), which is not valid for GET requests 🙂 okay, then dont add them to the route
júlio
júlioOP2y ago
I see, how would I iterate thru the parameters I pass then?
Pobiega
Pobiega2y ago
app.MapGet("/", (string name, int age, string address) => "Hello {name}, you are {age} years old and live at {address}!");
júlio
júlioOP2y ago
Ah just put them in the function, okay
Pobiega
Pobiega2y ago
well, AND the function signature 🙂
júlio
júlioOP2y ago
Yep I corrected after writing 😅 So what would happen if I did not pass any parameters, or if One of them was missing? Would I get a 404, would they get default value?
Pobiega
Pobiega2y ago
query parameters are optional by default thats their intended use
júlio
júlioOP2y ago
I see, well, the service kind of needs the parameters to be passed, else it will be kind of useless. Technically they will always be passed, since the only thing that talks to the services is code, but out of curiosity, is there a way to check if the parameters were passed?
FusedQyou
FusedQyou2y ago
They will have their default value. name and address will be null, and age will be 0. You can make them required, but then you need to add a custom class with the required attribute: https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-aspnet-mvc3/cs/adding-validation-to-the-model. Your method would then be this: app.MapGet("/", ([FromQuery] RequestClass request) => "Hello {request.name}, you are {request.age} years old and live at {request.address}!"); Note if I don't add the FromQuery, .NET will look in the body of your request, which is wrong.
Pobiega
Pobiega2y ago
^
júlio
júlioOP2y ago
I see, thank you for providing a link to the documentation I will try and make that work Curiosly, currently it requires the parameters
júlio
júlioOP2y ago
Pobiega
Pobiega2y ago
Ah, it respects nullable reference types. Didn't know that. thats neat. so you're getting 400 bad request
júlio
júlioOP2y ago
Now I don't know how to interact with it hehe
Pobiega
Pobiega2y ago
well you need to pass the querystring
júlio
júlioOP2y ago
Doing https://localhost:7232/name=WASD gets me 404'd
Pobiega
Pobiega2y ago
you forgot the ?
júlio
júlioOP2y ago
right That was it :) Would I still need to follow what FusedQyou posted?
Pobiega
Pobiega2y ago
its recommended but you dont need to
júlio
júlioOP2y ago
I see, I'll do it for learning sake
using System.ComponentModel.DataAnnotations;

public class Person
{
public string Name { get; set; }
}
using System.ComponentModel.DataAnnotations;

public class Person
{
public string Name { get; set; }
}
So I tried something that failed
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", ([FromQuery] Person p) => $"Hello {p.Name}!");

app.Run();
using Microsoft.AspNetCore.Mvc;

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", ([FromQuery] Person p) => $"Hello {p.Name}!");

app.Run();
júlio
júlioOP2y ago
júlio
júlioOP2y ago
So I would have to always implement a TryParse in my class?
Pobiega
Pobiega2y ago
try [AsParameters] Person p
júlio
júlioOP2y ago
That did it, yep I also noticed that the parameters are not case sensitive
Pobiega
Pobiega2y ago
correct. or rather, they should be, but accept both camelCase and PascalCase versions so Name and name should both work, while NAME should not, iirc
júlio
júlioOP2y ago
Any combination works actually At least on my machine
Pobiega
Pobiega2y ago
¯\_(ツ)_/¯ okay, maybe I'm confusing it with the json defaults
júlio
júlioOP2y ago
Okay, so I can now successfully pass parameters. This is like 30% or my goals for today this is nice The next thing I want to do Is the following I need to access a website (passing it the parameters I recieved), get the HTTP repsonce of the website, parse it (I recall you mentioned something about this the other day), and return the parsed result in JSON The previous code used something called HtmlWeb() and HtmlDocument()
Pobiega
Pobiega2y ago
Right, this is the http proxy
júlio
júlioOP2y ago
Are they both the way of doing this? Or are there more modern approaches?
Pobiega
Pobiega2y ago
I have no idea what HtmlWeb is, but that all sounds ancient
júlio
júlioOP2y ago
Yep :)
Pobiega
Pobiega2y ago
As a start, lets just make a http request
júlio
júlioOP2y ago
Apparently its from the HtmlAgilityPack
Pobiega
Pobiega2y ago
Okay, thats fine but I personally greatly prefer AngleSharp its faster and more robust
júlio
júlioOP2y ago
júlio
júlioOP2y ago
I would need to use NuGet for this?
Pobiega
Pobiega2y ago
yes, same as HAP HtmlAgilityPack is also a nuget
júlio
júlioOP2y ago
Did not know that I will see if I find something that sounds like AngleSharp
Pobiega
Pobiega2y ago
but lets ignore that for now lets make the request first.
júlio
júlioOP2y ago
Sure
Pobiega
Pobiega2y ago
step 1: you need to add a HttpClient(Factory) to your service collection builder.Services.AddHttpClient();
júlio
júlioOP2y ago
That is a factory for Http requests, correct? Requests are objects here, i think
Pobiega
Pobiega2y ago
no, its a factory for http clients 🙂
júlio
júlioOP2y ago
Oh
Pobiega
Pobiega2y ago
it handles all the complexities of creating and disposing of them for you makes life much easier
júlio
júlioOP2y ago
Noted
Pobiega
Pobiega2y ago
now, in your route handler lets request the factory add IHttpClientFactory httpClientFactory as a parameter in your route handler
júlio
júlioOP2y ago
So I'm a bit lost in terminology here When You say route handler, what do you mean?
Pobiega
Pobiega2y ago
thats the MapGet lambda
júlio
júlioOP2y ago
I see
Pobiega
Pobiega2y ago
the function you are declaring
júlio
júlioOP2y ago
So you also say as a parameter So I would have a Person and a IHttpClientFactory in the parameter?
Pobiega
Pobiega2y ago
yes you can decorate it with [FromServices] if you want
júlio
júlioOP2y ago
So much magic happening behind curtains here
Pobiega
Pobiega2y ago
yes, minimal APIs are... very magic I personally don't use "raw" minimal apis like this
júlio
júlioOP2y ago
You use Controllers?
Pobiega
Pobiega2y ago
for some older projects, yep. but new stuff, I use FastEndpoints which is a library built on top of MinimalApis
júlio
júlioOP2y ago
Interesting
Pobiega
Pobiega2y ago
but for now, this is fine
júlio
júlioOP2y ago
So when I access the endpoint, the httpClientFactory will be magically instantiated with something?
Pobiega
Pobiega2y ago
it will be resolved from the service provider 🙂
júlio
júlioOP2y ago
I see
Pobiega
Pobiega2y ago
Supported binding sources: Route values Query string Header Body (as JSON) Services provided by dependency injection Custom
Pobiega
Pobiega2y ago
Minimal APIs quick reference
Provides an overview of minimal APIs in ASP.NET Core
Pobiega
Pobiega2y ago
it has pretty much everything you need to know about minimal apis
júlio
júlioOP2y ago
I'll definitely give it a read, thank you for sharing
Pobiega
Pobiega2y ago
okay, so we have the factory in our handler now?
júlio
júlioOP2y ago
We do, yes
Pobiega
Pobiega2y ago
great. Lets get a client! var client = httpClientFactory.CreateClient();
júlio
júlioOP2y ago
So in this situation, I assume we will make a Single client, and the client itself would make the request, becasue we cant have a request wiithout a client, did I get it right?
Pobiega
Pobiega2y ago
we cant make a request without a client, yep asp.net doesnt itself know how to make http requests, it only kjnows how to respond to them 🙂 its a server, after all
júlio
júlioOP2y ago
I see So the HttpClietnFactory takes care of all the http requests we make and responces it recieves all we do is give behaviour to our route handlers
Pobiega
Pobiega2y ago
🙂
júlio
júlioOP2y ago
oops Let me try this The HttpClientFactory makes Clients, each client takes cares of the requests it makes and responces it recives Better? It's fine to use Clients in a scenario where the session is irrelevant? Isnt it a bit overkill, or is there no way around it?
Pobiega
Pobiega2y ago
you need a client to make a request the whole point of using the factory is that we dont want to care about where the client comes from, when its created, disposed etc we jsut want a client
júlio
júlioOP2y ago
Okay, noted
Pobiega
Pobiega2y ago
a client isnt an ongoing session, its just something that can make http requests
júlio
júlioOP2y ago
It isnt? Interesting
Pobiega
Pobiega2y ago
so, now that we have the client... lets make a request.
júlio
júlioOP2y ago
Out of curiosity, is there some website online made for this? Something that we can practise sending requests with expected responces?
Pobiega
Pobiega2y ago
sure for HTML responses, any static page will do lets start with a great webpage: https://vecka.nu/ it just shows the current week number 😄
júlio
júlioOP2y ago
That is perfect!
Pobiega
Pobiega2y ago
so, to get the entire webpage... we just do
var content = await client.GetStringAsync("http://vecka.nu");
var content = await client.GetStringAsync("http://vecka.nu");
this will return the entire webpages source html as a string you can then feed this string into HAP or AngleSharp to start parsing it AngleSharp has some ways to load webpages built in, which would remove the need to do this yourself. btw, since you said this needs to be fast, manually parsing it might be a lot faster than using a HTML parser, if the data is easily parsed.
júlio
júlioOP2y ago
That might be the reason they make a Parser from scratch Would have to check with the previous maintainer (im asking im rm :) )
Pobiega
Pobiega2y ago
if the HTML is fairly straight forward, you can optimize a lot by making assumptions (that AngleSharp can't, since its a general purpose parser)
júlio
júlioOP2y ago
Well the Parser itself is a bit weird honestly Okay so the flow they did was The HTML response was loaded into a HtmlDocument (from the HtmlAgilityPack) and they they did parsing like this
HtmlDocument doc = new HtmlDocument();
doc.Load(await resp.Content.ReadAsStreamAsync());

HtmlNode p = doc.DocumentNode.SelectSingleNode("//p[@class='user-nif']");
HtmlDocument doc = new HtmlDocument();
doc.Load(await resp.Content.ReadAsStreamAsync());

HtmlNode p = doc.DocumentNode.SelectSingleNode("//p[@class='user-nif']");
Stuff like this to get the values
Pobiega
Pobiega2y ago
thats not weird at all imho, thats just your standard XPath query but for HAP to do that, it needs to parse the entire document and build up a tree
júlio
júlioOP2y ago
The weird was not refering to that flow, it was referring to another thing they called a Parser that is soemthing else i was mixing up, my bad So would I be able to do that with the technology you mentioned? It still searches for something So no real optimization here They dont really assume the format of the data They then load that into a object and in the object they have a public FormUrlEncodedContent ToFormData() which I assume its to put the information on JSON format So that they can return the object in the end and magic happens
Pobiega
Pobiega2y ago
Im just saying thats a possible avenue for optimization but you can absolutely get started with using HAP and/or AS directly
júlio
júlioOP2y ago
I'll note that down, maybe in the future I'll talk to them about it and see if I get approval to do that, thank you for pointing that out Currently they just want me to split the services and gave be a bit of freedom of the technology I can use However Remember talking about IIS and that you advice me to use Kestrel Well I brought that up talking to the boss, I did some research and sharing it with him And he told me It would be hard to convince him to change to Kestrel lol
Pobiega
Pobiega2y ago
what IIS is windows only, for one. like, you literally can't use it with kubernetes kestrel isnt some weird fringe software either, its the default asp.net webserver
júlio
júlioOP2y ago
Yeah I also (after doing some research) I assumed he would be happy to switch, I was also surprised with his reply Maybe there is some aspect of IIS he knows that I dont, I assumed
Pobiega
Pobiega2y ago
Or rather, he is stuck in the past 😄
júlio
júlioOP2y ago
regardless, in my free time I'll gather up some facts and make a rpesentation to him Maybe! :D really? I did not know this
Pobiega
Pobiega2y ago
I mean its a windows service how would it work with a linux based container system? you also want each container to be self-contained
júlio
júlioOP2y ago
I dont know, I never tried it but that makes sense yeah
Pobiega
Pobiega2y ago
thats why you use kestrel, as it comes with the .net runtime your gateway/load balancer will "hide" kestrel anyways so its not going to be exposed to the client anyways, using HAP, you'd get the time from vecka.nu like...
var content = await client.GetStringAsync("http://vecka.nu");

var document = new HtmlDocument();
document.LoadHtml(content);

var weekNumber = document.DocumentNode.SelectSingleNode("//time");
var content = await client.GetStringAsync("http://vecka.nu");

var document = new HtmlDocument();
document.LoadHtml(content);

var weekNumber = document.DocumentNode.SelectSingleNode("//time");
júlio
júlioOP2y ago
I think the "can't be used with Kubernetes" will be enought to force him to change
Pobiega
Pobiega2y ago
and the value is in weekNumber.InnerHtml
júlio
júlioOP2y ago
So I would still use HAP for this?
Pobiega
Pobiega2y ago
I mean thats what you said no?
júlio
júlioOP2y ago
I ask because you brought up other technologies Maybe I expressed incorrectly, I ment to say I have freedom with the parsing
Pobiega
Pobiega2y ago
you can use whatever you want. HAP does the trick, but its probably not the fastest. I would suggest writing some benchmarks if you want to have reliable data on speeds
júlio
júlioOP2y ago
I can do that actually wekll first I would have to get the thing running but after that, i might, it seems like a nice thing to add After installing a packet with NuGet, I would need to restart the project for it to recognise the types? wait nvm figured it out Thank you for the help so far, it has been incredible the amount of progress I was able to do because of you. I will go eat now, and then experiment with the new things I learn so far, and read the links posted above Thank you :)
júlio
júlioOP2y ago
júlio
júlioOP2y ago
Well this is weird.
Pobiega
Pobiega2y ago
you need to do that before you call builder.Build();
júlio
júlioOP2y ago
builder is being deduced to const? Oh Why?
Pobiega
Pobiega2y ago
what do you think builder.Build() does?
júlio
júlioOP2y ago
I see
Pobiega
Pobiega2y ago
you can't modify the builder after it has been built, its as simple as that
júlio
júlioOP2y ago
Its a configuration
Pobiega
Pobiega2y ago
yes
júlio
júlioOP2y ago
Okay, makes sense Nice how the IDE detects this
FusedQyou
FusedQyou2y ago
It didn't, your application complained 😛
júlio
júlioOP2y ago
Oh, that was a throw sorry I just came back from lunch I probably took too much sun in the head ahaha So I'm reading the following documentation: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis/route-handlers?view=aspnetcore-7.0 In it they mention something called "Route Groups" But I didn't really understand what they say there
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);

return group;
}
public static RouteGroupBuilder MapTodosApi(this RouteGroupBuilder group)
{
group.MapGet("/", GetAllTodos);
group.MapGet("/{id}", GetTodo);
group.MapPost("/", CreateTodo);
group.MapPut("/{id}", UpdateTodo);
group.MapDelete("/{id}", DeleteTodo);

return group;
}
So with this code we give route handlers to each route, and put everything in a Route Group? And how does that allow me to do things like this?
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();

return TypedResults.Created($"{todo.Id}", todo);
}
public static async Task<Created<Todo>> CreateTodo(Todo todo, TodoDb database)
{
await database.AddAsync(todo);
await database.SaveChangesAsync();

return TypedResults.Created($"{todo.Id}", todo);
}
The Task<Created<Todos>> is throwing me off a bit
FusedQyou
FusedQyou2y ago
It's an extension method and the second method is passed as a delegate Honestly you might aswell make controllers at that point
júlio
júlioOP2y ago
Why?
Pobiega
Pobiega2y ago
RouteGroups is just a way to group a number of handlers under a base route this is pretty much what controllers do
júlio
júlioOP2y ago
I see I probably wont use that tho Maybe after understanding how many routes I have\ And still I dont think I'll need that The hardest part for me currently is reading the previous Service code each .cs file is like 6k lines of code I think that theoretically there would be a way to copy paste the hole thing, change a few key setup stuff and get it working
Pobiega
Pobiega2y ago
that is a lot of code.
júlio
júlioOP2y ago
im just far from that level yet Yep, that x10 files plus some other smaller ones okay maybe not 6k lines each avg is like 1.5k lines, I just happened to start with the biggest ones now that I realise nice aiming lol Im noticing a pattern
Pobiega
Pobiega2y ago
I thought you said these things just forwarded a request and scraped some answers into json?
júlio
júlioOP2y ago
Well They to in theory Its like this The things we access dont have a API so this is like a API for them we give them functionality we want, and make code that replicates the behaviour translating the HTML pages into JSON replies like if we were interacting with a API
Pobiega
Pobiega2y ago
still sounds like a lot of code to do that
júlio
júlioOP2y ago
I know right! Well I also notice they do several entities in one file so like one big API that covers N websites the biggest file accesses over 10 websites and over 15 routes for each website its pretty flexible but the code is huge Maybe I should start with the smallest one So that I get a hang of things the smalles is 450 lines thats pretty manageable actually I think the website for that smallest one has a API probably the API doesnt have the functionalities we are looking for tho So what we do currently is the folowing Well I still dont fully understand how it works honestly just part of it Anyways, this is what is being done LEts say we want to access some information on website X website X requires auth so we make a login request the class that manages this things keeps track of cookies so this is how we get the behaviour of a Session we can then make more requests to the website for each request we pass the login credentials the class checks if there is a session opened for thoes credentials and uses that session for the request now I dont know much about this whole web stuff, I'm just learning as I explore the code Is this a common approach? Honestly the thing we do is not very common at all, so maybe this is the only approach now that I think about it
júlio
júlioOP2y ago
júlio
júlioOP2y ago
Any clues on what the Procudes and Route mean? Are they required?
FusedQyou
FusedQyou2y ago
Sorry I can't read all your messages right now Route specifies the route to take to an endpoint. In this case it's on controller level, which makes it the base endpoint for any endpoint in there. So any endpoint has to traverse api/viactt/, and then additionally their own added route if added. As you can tell, [controller] indicates the name of the controller, without Controller prepended to it. I honestly never used Produces. I guess it's a hint to indicate what the endpoints return, because modern .NET is smart enough to manually add that header with responses, so it's probably for something like Swagger to understand what the endpoint returns type-wise
Florian Voß
Florian Voß2y ago
they are optional. I think its for browser. Certain browsers like Firefox have formatter for json, they dont display it like plain text. We show browser that this is json tho
FusedQyou
FusedQyou2y ago
Didn't know that 👍
Florian Voß
Florian Voß2y ago
well its just a guess i dont "know" it either xD
FusedQyou
FusedQyou2y ago
Oh 😄
Florian Voß
Florian Voß2y ago
since it defines a MIME-type I just assumed this is what its used for. MIME-types exist to tell browser how to understand data so according to chat gpt what it does is check if request contains the mime-type in the accept header, if so it will return the response formatted as json with content-type header set to application/json. If client does not contain any supported format in his accept header this will return 406 to any response to indicate that the requested ressource cannot be served in a format that the client can accept
Pobiega
Pobiega2y ago
application/json is a content type header value, and yes, browsers look at that to decide how to display the content. However, the [Produces] attribute is specifically for stuff like Swagger you are documenting your API behaviour, which swagger and similar tools can use Its pretty unusual to "automate" login and handle stateful actions in a website without API access in general, but I dont see much alternatives if thats a requirement. I hope you have explicit permission from the websites you are doing this to however
júlio
júlioOP2y ago
What do you mean?
Pobiega
Pobiega2y ago
if a website doesnt have an API, that usually means they dont intend for automated usage so unless you have permission to do this, you most likely violate their TOS
júlio
júlioOP2y ago
That makes no sense Why would making my own API to something that doesn't have a API be against TOS? It just changes the way we interact with the functionality they supply
Pobiega
Pobiega2y ago
I'm not saying it is, I'm saying it likely is. Its pretty common with TOS statements like "any non-supported automated use is prohibited" or similar. The idea being if they wanted you to automate their webpage, they would have an API for it
júlio
júlioOP2y ago
Well, we talk to them regularly, asking them to make APIs, they never get to do it, and the alternative they give us is to make APIs around the website
Pobiega
Pobiega2y ago
That counts as explicit permission :p
júlio
júlioOP2y ago
What can we do They are so backwards honestly... oh well this is another topic :) So I have a question Not sure how to ask it Do you recomend any strategy when dealing with large code bases?
Pobiega
Pobiega2y ago
Divide and conquer 🙂
júlio
júlioOP2y ago
I did some searshing in the code and alot of things the previous maintainer doesnt even know, and others are obsolete Plus I made a new thread todday asking about the code structure because Im not used to work with VS, and its a bit weird
Pobiega
Pobiega2y ago
I would probably make a class library and write a console app to interface with it, to test it out
Pobiega
Pobiega2y ago
and then when the library is "complete" I would integrate it with your web service
júlio
júlioOP2y ago
But what wold the library do tho?
Pobiega
Pobiega2y ago
well, looking at that thread you posted, you already have libraries each of those HelperViaCtt etc projects are class libraries
júlio
júlioOP2y ago
This is what I have trouble understanding So from the tutorial I followed I basically in the Program.cs file I made a route then I gave it a route handler and that was it Now in this project the helper had a folder called Controllers, and in it there are basically controllers for every class library and the code in the controllers is kinda of the code i made form the Program.cs
Pobiega
Pobiega2y ago
Lets move this discussion to the other thread? it seems to be more relevant there
júlio
júlioOP2y ago
Yes, you are right
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