Transcripts
1. Introduction: Hello and welcome to my course, ASP.net Core minimal
API development. I'm your instructor for war Williams and I'm a
software engineer and lecturer and I
have been doing this for the past 12 years. In this course, we're going to get an understanding of how we develop minimal APIs
using dotnet six, we're going to understand whole API verbs
work whole sequel, light and Entity Framework
Core combined to give us a place to store
and retrieve data. We'll also look at dependency
injection and whole swagger documents help us to
interact with our API. Throw this course are going
to be using Visual Studio 2022 and sequelae For dotnet. And Visual Studio 2022 is
required to use dotnet six. It is a fully featured
and extensible IDE, and it is very powerful
and allows us to do so much more for development. So without further ado,
let's get started.
2. API Overview: Hey guys, welcome
to the start of this new section
where we will be working on a RESTful API to
complement our mobile app. So we looked at all the
basics of Maui already. But now we want to go
into building a real app. And generally speaking,
mobile apps communicates with APA is which is why a lot of them require
Internet access. Now if you're not so familiar
with what an API is, I'm going to walk
you through some of the basics right now. And if you really want to delve into more of
the details that you can check out my other
courses where I bring you through the ringer
with API design. But for this course
are going to keep it simple enough that
we can get an API up and running and see
how we can consume and interact with this API
through our mobile app. Now we're building
a RESTful API. And wrist is an acronym for Representational
State Transfer. Essentially it's an
open standard that allows for any kind of client to be able
to interact with some endpoint and access some, what we'll call IT resources. For instance, let's take an
application like Facebook. We are facebook on
our mobile phone, or if it's on our Internet, our Internet browsers,
we have it on various devices and we
have apps for Android, for iOS, et cetera. The fact is that each of these apps is not feasible,
built from scratch. It's actually just
interacting with an API that Facebook has developed
and keeps on developing. And that is why when
you get up updates, what maybe what they do
go stay in something, the API and they have
to update the way that up interacts with that API. But essentially, the
intelligence rests in the APA. And then because it's
an open standard, it doesn't matter if
it's an Android device or a Windows device, or your mobile phone, or your mobile watch or
your smartwatch rather. All of them can interact with
this open standard APIs or web service that generally conforms to the rest
architectural style. When we talk about
APIs and restful APIs, there are certain
concepts that we want to make sure we're
comfortable with. One is uniform, which means
that there is a standard way to formulate your URLs
and meet those calls. It is still less. So you generally don't
find that cookies and other files are generated on the device to
support the API. Call is made once I
call this finished, it, it forgets about it. There's nothing really
held on, right? It's cacheable, meaning
that sometimes you have inflammation that is
always being requested. So instead of going to the database or the data
store, every single time, we put a cash there so that the API can respond
more quickly with inflammation that
is more frequently accessed and generally
doesn't change that much. It is layered. So you have different
parts and layers to the API to constrain what can be done at different levels. Or resource generally
represents bits of data or an object in between the database and the
client application. And generally
speaking, when you're naming your RESTful
API endpoints, you want to be self-descriptive. So if it is an endpoint to deal with personally
inflammation, then you want to make sure
you say person inflammation. So those are just principles. Next up we have
the HTTP methods. Now we have different methods in the forms of get,
put, post, delete. Those are the most popular ones that you will see being used. There are other ones. But generally speaking, when we're dealing
with a Datastore, we want to carry
out for operations. We generally call that
crowd operations. We want to create
data in the database, wanted to retrieve the
data in the database. We want to make changes
to it or update it, and we want to remove
it or delete it. So see IUD. So get handles the
retrieval when you want to view the record
or a bunch of records. Putting I GET request, put is the u, which is update. You also have patch, but that is a topic
for another time. Put the easier one
to implemented, we'll be working with that
for our purposes here. But we send PUT
requests whenever we want to make an
update to the data. We have the post request
whenever we want to create data. And then we have the
delete requests, which I think is
self-explanatory, if not the most
self-explanatory, one of them all, then we
have the HTTP response. So that was the requests
that we just looked at. The response is what
the server sends back. So we generally have one XX
and XX just means number, numbers like 100,
between one hundred, one hundred and ninety-nine. The x-axis represents
anything from 00 to 99100. Status codes
generally talk about communication on transfer
protocols to 100. Generally peaks success
in the operation. 300s was that there
was a redirection. 400 shows that maybe there was some bad data center
or from the client. So the user mid are sent data that the
server couldn't process. And so we would say it was bad, a bad request or you
requested something that couldn't be found
like a 404 error. I'm sure everybody can identify
with a fluorophore error. And then we have the 500 error, which means that the server
is where the problem was. The data came in, but
maybe you didn't call into that database connectivity
issue or the server was done, then the API would respond
with a 500 response. So those are general response
quotes and it's very important to get those
rights in good API design. So all of this to see that
our API will serve as a point of interaction between our mobile app and
some central database. Everything we do
on the mobile app, we want it to flow
through the API because that's where the
real intelligence will be and that is what we are going to start
this journey on. So in this section
we're starting the API design and we'll
walk through the basics, doing enough to get it up and running and understand
it once again, if you want more details, you can check out that
course ultimate ASP.net Core API development guide. You can check that out for
everything you need to know about proper API
design from scratch. In this course, we're
keeping it simple. So in the next lesson
we're going to set up our API project and
get the ball rolling.
3. Setup Project: All right guys,
welcome back. So let's us jump right into it. We're going to open up
our Visual Studio 2022 and we're going to proceed
to create a new project, but I want an empty solution. So I prefer to start off
with an empty solution. So that are blank
solution rather, so that I can give the solution a name and then add the
projects afterwards. So we're going to be working on a shopping cart
mobile app, right? So shopping cart list, so I'm just going to
say shopping cart list. That is the name
of the solution. So we can go ahead
and create that. Now once we have the solution, I'm going to create
a new project. So I'm going to just
directly the solution, Add New Project. And then we can add
an API projects. I'm just going to just
search once again for API. And then I'm going
to go with a C-sharp ASP.net Core Web API. And then I'm going to call
the shopping cart list dot API. Then we hit Next. And now here are some
interesting options for us. And like I said,
I want to keep it relatively simply,
simple for us. One, we're going to be
using dotnet Core six now with Visual
Studio 2022 preview, you can go back to five, which at the time of
this recording has reached end of life pretty much so you probably don't
want to go there. Dotnet Core three-point one
still has long-term support, so does dotnet six and
dotnet seven is in preview. For stability reasons, I'm going to proceed with dotnet six. And we can put in an
authentication type. But for now, let's just choose none because we will do
that manually later on. We can configure for HTTPS, we don't need darker. Now, here's where it
gets interesting. We can choose to use
controllers or we can uncheck, so we can use minimal APIs. Traditionally we would
always use controllers, but I think this would
be a good time to try and see how the
minimal API looks. Especially since this is
really a lightweight app, but it might just
grow on us anyway. So I'm going to untick that untick use controller so that we can use minimal APIs, leave open APIs support. And then the next option that is rather interesting though, is whether or not we want to
use a top-level statements. So with dotnet six, top-level statements
would have been like the main function and the
main namespace and so on. So certain persons
would have said they prefer to see
it done in six, introduced minimal
style classes where you don't necessarily need to be
that explicit at the top. So you can, you can choose
which one you want. I'm not going to use the top-level statements
because I like them like that. And I'll just hit Create. Alright, now we have our
API project created. So if I go to program.cs, notice if you're used to seeing the controllers folder
in your API development, you're not going to see it here because we untick
the US controllers. If you chose to use controls, no problem, you should be
able to follow along fine. But because we're
doing minimal APIs, or I chose the minimum
API templates. What happens is
that we're going to see everything happening right
here in that program.cs. So once a program executes, it builds up all of the
dependencies it needs. And then it goes straight
into executing the code or knowing what coding is
execute and then it runs. So the API will sit there
and wait for requests and everything is running from our program.cs pretty much. I'm just going to run
this to make sure that it is up and it works. And it will launch this browser showing
us our Swagger doc. So because we chose
open APIs support, we automatically have
swagger built into our API. So once we run this, we'll
see the documentation. So the more endpoints
abilities is more of this document expands
automatically. So that's it for us creating. When we come back, we'll
set up the course policy.
4. Setup CORS Policy: All right guys, so
in this lesson we're setting up our course policy. And I tend to do this as
one of the first things. Anytime I build an API, why? Well, the API by design is supposed to be consumed
by other clients. Other being clients that may not necessarily be on the
same server as the APA. No cars is a general
security term for any app that is
hosted on the Internet. And generally speaking,
this policy would dictate whole different resources are
different requests rather, can be facilitated by
the app being requested. All of that to see. The course policy allows
us to reject requests from certain sources are all
sources are a low requests. So when we have the
mobile up somewhere else, or 60 million mobile
apps all around the world and our APIs
on one server somewhere. We'd need to have a
course policy to say, well, I don't know, I can't keep track of 60 million requests and
60 million mobile phones. So I'll just allow
anybody to talk to me. Of course, we can add other
security at another level. But for now, we'll just use the course policy to make
sure that we can facilitate requests coming from mobile
apps after the fact, right? We'll go up to this is what lines seven in the program.cs. And like I said from
the last lesson, I didn't choose to use
the top-level statements. So it just gets straight
to the point, right? It just starts the
code because it already knows it's
the program.cs, so it doesn't need
to declare int, void, program class,
etc, etc, etc. So not void class, you
know what I've seen? So let us go into it. So we say builder dots
services, dot, add cars. Right there it is. And what we're going
to do here is set up some options which will
guide the configuration. Alright, so we said Options
and then use curly braces. And let me make
this a bit bigger. Make sure that we can see give myself a little more realistic. It makes sure that we can all see what's happening clearly. Alright, so build the dots services that add CORS
on the web or options. And then inside of our
options are going to have options, dot, add, policy. So this is our course policy. We have to give it a name. So I'll just say a low all because I'm not willing
to put any restrictions. So yes, it's literally
going to be Hello all. And then I'm going to start
up another lambda expression. Just see a Lambda. And then this is like
a builder functions, so I'll just say a dot and then I can say
allow any header. So that means any type
of request that comes in, gets pulled, etcetera. Although it began,
see any origin. Wherever it is,
originating from, it being the
requests are low it, and then I can see a low, any method actually
allow any method is the HTTP method that's coming into
header is different. I apologize, the header is up
parts of the request body. And sometimes certain
hitters could be militia. So we'll just follow any header, allow, any method, etc. And there we go. So that is the policy
that we have set up. No, we need to let
the middleware, so this is where we
build up our services. But then the
middleware starts at the up declaration here. And he noticed that the
variable here changes, right? It's, or the object
name changes, it's up instead of Builder
dots, services or whatever. And so then what
we need to do is let the AppBuilder know
that it should use cores. So I tend to put this
underneath that. So I'm just going to
say up use cores. So use the cors
middleware and please apply the policy that was
created called a low. All right, so watch for typos at that point because
that's a magic strings. So you might end up debugging
nothing if you feel to spilled these two
cart to the right. So that is really it for
setting up our course policy. I can stop here because
there isn't really any tangible way to validate
this at this point. Outside of maybe
running the API, trying to host it
somewhere and then trying to access it from
another machine. So that's really
our course policy. I already explained why
we need it to do this. So when we come back, we'll
continue building our API.
5. Setup SQLite Database: Hi guys, welcome back. In this episode we're going
to build out our database. Typically, of course,
for an app that is going to be scaled
for large usage, you want to use an
enterprise grade database like Oracle or
Microsoft SQL Server. And then the flagship object
relational mapping tool, or the, the library that dotnet Core gives us the
interact with the database. The flagship one is
Entity Framework Core. Know it has connectors
for many other databases, so I'm not telling
you that you have to use the database
I'm about to use, but I'm keeping
it simple enough, but I will explain the general concept
to you so you can appreciate why I'm
making these decisions. So for this course, I'm just going to use a
sequel database which will just sit inside of the
folder with the APA. But once again, in an
enterprise-grade application, you'd want to connect to
some remote server for an enterprise grade database
like Microsoft SQL Server. So in order to get Entity
Framework into our project, I'm going to right-click the project and then
go to NuGet packages. And then we're just
going to go to Browse and I'm going to search for Microsoft dot Entity
Framework Core, sequel light. Once again, if you want to
use a different database, so maybe you already
know how to wire it up to SQL Server. Then you just look for Microsoft but Entity
Framework Core, and you would see the different
ones die for SQL Server, for my SQL, etc. So generally
speaking, the name is consistent where you just
say Entity Framework, Core, duct, and the database
engineer, you prefer. Then you would find
the libraries. Someone to download. Entity Framework Core
does sequel light, and that will come with a
few additional libraries. So let me go ahead and
download and install that and accept
anything that comes up. For this, I will also
need another library, which is Microsoft dot data
dot sequel light dot core. So I can go ahead
and grab that one. And that allows me to do some
other important operations. I'll go ahead and install that. Now let's jump back over to our program.cs and then
start wiring this up. So I'm just going to put in some configurations and then walk you through them. So what we're doing here is
we're setting up a folder. All right guys, so
let's jump back over to our program.cs. And I'm just going to put in some configuration
lines and then walk you through what's
happening when I'm setting up the database path. So the database path
is just going to go to the root folder and create a file called
shopping cart dot db. Then the connection string I'm just calling
a con for short, is equal to a new
SQL lite connection. Of course, as you go along, you will need to include some
missing using references. So just include them
as you see them. And the data source is going
to be equal to the DB path. And then we say build out
services at the DB context. And we have shopping
cart DB context, which has a red line because
it doesn't yet exist, but go ahead and put
it in regardless. And then we put in
the option that we're using sequel ITE, and that is our connection. Alright, so we can
create this file. I'll just Control dots and I'll generate that
in a new file. So then we have the
shopping cart DB context. Now I'm going to firstly
meet this public and then I'm going to make it
inherited from DB context. So once you do that, of course putting any missing, missing using
reference accordingly. So now that I have
this DVI contexts, I want our constructor. And then this
constructor is going to initialize our tick in the DB context, DB
context options. And those options would
take itself as its type. We're just going to call that Options and then we'll pass
that down to the base, right? So essentially what
we're doing is injecting the options coming in
from our program.cs. And these would be the
options here, you see light. And they were just passing
it down to the base, which is the DB context
that we're using. Cql ITE. Alright? No, we really just
need one table. So I'm just going to say prop. And then I'm going to
create a new data type. I'll just call it
a shopping cart. And let's call this
shopping carts. Alright, so if we're building a mobile
app, think about it. You're building a
mobile app to help people compile what they
want when they go shopping. That's essentially what
we're doing here, right? So later on as the app evolves, we might want to put
on like some way to identify which shopping
cart record belongs to, which user or which which user has those
interests into two. But like I said, I'm
keeping it very simple. At this point as we evolve, we can put in more fancy things. And I put this in
the wrong place, that should not be
in the constructor. I apologize, that should
be after the constructor. There we go. So this is the property
in the EB context. Within the Framework Core, I'll have to do is put
in the properties. And actually this should be
DB set of type shopping cart. So wondering why
it looks so weird. So DB set of type shopping cart gets it's not shopping cart
is a data type that we need. So I'll just create that. And I will just generate
that class in a new file. So now we have that
shopping cart file. I can just press F 12 with it's selected and it will jump
over to its definition. No, what does a
shopping cart have? No, most entities,
and I would say every entity in your database should always start
off with NAD. Alright? We could have item
name, item name. Alright, as I'm
on this properly, I'm here trying to
take shortcuts, but it's like my, my my programming
senses are tingling. One, when you're adding
something to a shopping cart, you would use probably type
in the name of the item. You'd probably
typing the quantity that you expect to pick up. And maybe you'd want to set a flag to see if it
is selected or not. Have you picked it up or not? So here is a string
for the item name. And then we have int
for the quantity. Or it could be double for the quantity because you
could say 1.5 or something. Oh no, you can choose the
appropriate data type, so quantity and a
Boolean that says is. So those are our
datatypes, right? Know that we have those
bowl I was running. So now that I have the
basic template for what my shopping cart
entry will look like. It says, jump back to the
shopping cart DB context. And what I'm going
to do is override the method for on
model creating. So when you write
the word override, it will ask you what would
you like to override? And we're overriding
a non-model creating, and then it will just
generate all of that for us, so we need that first line. Then I went to see a
ModelBuilder dot entity, that shopping cart. And then I want to
say that has data. So in this case, what
I'm doing is I'm going to seed the database with some data so that when
we run our API to check, we'll see data in there, right? So has data takes a collection of objects of whatever type you
are specifying here. So I would just say new
shopping cart and then give this an ID of one is picked
up would equal falls. And item name would be, let's see, soap and
that's a string. And then the final one
would be quantity. And we need three bars of
soap, for instance, right? Then it's just going to take
a collection pretty much. So we can just comma, separates these objects as many
objects as you want. Of course, each one should
have a different ID, as id will automatically be seen as a primary key
in the database. So let's mix it up a bit. Let's meet that one true. And this would be bred and we should pick up two
loaves of bread. And this one can remain falls, and this one should be shampoo. I'm just making this
up as I go along as it's not Mariel shopping list. There we go. So we have three items
that we want to seed into our database table
when our app runs. And we have wired up pretty much everything to have a database at the time, at runtime, right? So what I'm going to do is go to NuGet packages and install one more package,
at least for null. And this one would be Entity Framework
Core dock tools that will give us access to certain
commands that we can run because we need to create
the table in the database. We'll go ahead and get
the tools, install that. And if you just look,
you can check out my Entity Framework Core course if you're not so familiar, not so comfortable with
Entity Framework Core. But in a nutshell, this allows us to run these
commands where we can add a migration and
update it to be switches, what we're going to be
focusing on right now. So let's go to Tools and go for NuGet package manager
and launched that console. And then I'm going to say
add hyphen migration. And then I'm just going
to say create database. And then we press Enter, let it think about it for a bit. Then once it has done that, we get our migration file, which I'm not going to
go into the details off, but in a nutshell is seeing create table and
insert the data. And we had seeded three
records in, right? So the next command would
be update hyphen database. If the database doesn't exist, it will go ahead and
create it and then go ahead and put in
all of the records. So at this point our
database should exist. You can go ahead and build
and run and just test it. But of course we haven't
built the end point yet. So when we come back, we'll build the API endpoint
that allows us to then query or retrieve these records that we know are
in the database.
6. Explore GET Methods: Hi guys, welcome back.
So we just set up our database now
we want to set up our first endpoints so we can
see what's in the database. Because when the database got created at runtime
on modal creating, we wanted to see
these records in, so at least these records should be in the
database and all we want to at least retrieve them
and see how the API works. So what we're going
to do is follow the template that has
been given to us. Yes, it's weather
forecasts and yes, the data is static inverter in terms of just
being this array. But the principle behind how we're going to read
our code is the same. Underneath or weather forecast right above the app dot run. What I'm going to do is
write up dots, mop, get. Alright, so what
happens is that for all of the methods that
you'd want to use, you can see a map and
then the method type. So we want to do get, gettier of my PUT, post or delete, etc, right? So as we go through them, you'll see that
kind of patterns. So we will see mop get, and then we have to
give it the address. So to get the weather forecast, you have to see the URL or the server URL
slash logo forecasts. We want to get the
shopping cart items. We would say slash in our
string, slash shopping cards. Alright? And then what we want to
do is do an asynchronous. Then we get pretty much so Async and we need our representation
of our database. So I'm going to
collapse anything that is not absolutely necessary. So we can see most of what we need to see in
one shot, right? We need some representation
of our database. So I'm going to have to see async database create an object. I'm just going to call it dB. And then we create
a Lambda arrow. And then we can write
our code pretty much. Alright. So I'm just going to move this down and end with a semicolon. And then our function
code will be in this section of
the method, right? So I'm going to say a weird DB. Dots shopping cart,
college shopping carts. That's fine. List. So pretty much I'm saying
select star from that table. Alright? And pretty much that's
what it will do. So let's review this, look at this nice and clean. So if you weren't
used to minimal APIs and you are used to
controllers, you know what, As you'd have a
whole big file for really just this line of code with old method
and everything. So this is a nice
succinct way to see. When you hit this endpoint, get a copy of the database
from our service builder, query and return, whatever. Then that's really
all we need to do. Alright, so let
us test the toes. I'm just going to
go ahead and run. Alright, so now let
us test this out. I'm just going to go ahead
and run the API project. And immediately you
will notice that we have our new
endpoints, right? So we have our GET endpoint. We can expand that
and we can see it, try it out, and then
we can execute. So at this point it should
hit the method that goes to the database and
retrieves our records. Excellent, alright, so now we
know that one or API, yes, it's running to our database has been created and the
records are there in three, we are able to retrieve them and interact with our
database through our API. So before we leave, I'm just going to implement
the other type of getMethod. So I get to retrieves
data, right? Typically, you either want all of the data
or you want some, some of the data. And the way I determined
the sum would be some. So ME SUM. But the way you determine what subset of the data
you want would be through some parameter that
you provide and then you run a query
based on the parameter. All of that to see
difficulty in an APA, you have two types of gates. Before any other type of gates, you have the Git, which
returns everything. And then you get by some
unique identifier which generally should
either return one or return nothing if he
couldn't be found, right? So all I'm going
to do is copy and paste this getter method. I'm going to modify the
URL and I'm going to see shopping cart slash
and then put in a template using curly
braces and say id. So I am expecting that when
you call this endpoint, you're going to
provide some id value, meaning you want the
record with this ID. Now, in this In the delegate header here, I'm going to add a parameter to facilitate
the collection of the ID. So I'm just going to say int id, comma shopping cart DB context. We know that this
is already provided by the, by the system. So that's not coming
in from the user, but we are facilitating the incoming id value
from the user here. Then our query is going
to look differently. We're not going to see
a weird shopping cards. Go to the database
and find a sink. And then I'll give it ID. And then I can
qualify this a bit. No, because it's either
going to find it and return it or we don't want
to find it and return it. Or we want to maybe
return not phoned. So I can see is shopping cart. So this is my way of seeing is whatever it was
retrieved here, a shopping cart object. Alright? And I can do a lambda
expression and I'll just break lines so that
it's not so confusing. So let's see. I would want
to return a result of type, okay, with the data that
you have requested, which would be the
shopping cart object that was retrieved. And I'm sure, I'm sure if you're doing
discourse here familiar with basic C-sharp. So lambda expression, not
lambdas or a ternary operation. Oh my, I'm sorry about that. So ternary operation would be a logical operation where
you see what is the, what is the logic I'm
assessing? Is it true? Do that is it false? Do that. It was found and it is an object of type
shopping cart then, okay, we're returning that. Otherwise Buddhist see
results start not phoned. And that would give that 404
that we discussed before. Now, another one that I would probably want to do right
now while we're here, is what if I wanted to find all the items that have been picked
up quickly, right. So the thing is that
the arrest APIs yours, you can use it, how you can create
it all you want. You just make sure that
you follow the standards. So I can create another
important here to see picked up. So if they call this
endpoint is just supposed to return items that
have been picked up. Because remember
wherever that flower you see the picked up
or not picked up. So if it's picked up, only those should
come back here. This is going to
show everything. And this one is only going
to bring back one item. Alright, so far picked up, what I'll do is say db dot
shopping carts dot where. And then we put in
our Lambda expression and our condition
where he is picked up. Alright? And because it's Boolean, I can just leave it like that. And then I just
Piracy told to list, which is our executing statement for or if course statement. And that's it. And pretty much we just
created three gets endpoints in a manner of
minutes, in a matter of minutes. So once you get to everything, wants to get only
picked up items. I don't want to get something
specifically by Adi, so let me just run this quickly
so we can assess or work. Alright, so we have swagger, we already tested gets also
on bother with that one. We know that we have at
least one item that picked up was true someone to
try it out and execute. And I shouldn't get back
everything instead, I only get the one item that is picked up,
his true Excellent. And then if I want one by ID, I can see try it all done. I provide only the ID of one. The record I get Buck
has ID of one, right? If I have provided ID of ten, knowing that I don't know
what I asked for ten that I'm getting that for all
four response not found. So that's all
responses work, right? Notice that when
he was successful, we got back a 200 chord. Alright, so that's the O key
response to 100 is okay. So when you want to be specific, you can see results that okay. If you just as long as
you return something, it will automatically
be on. Okay? So that's really it for us
creating or get endpoints.
7. Explore PUT Method: All right guys, So we're
moving on in our adventure and we're going to go on
to the put method, right? So what we have so far would be getting
methods we can retrieve, but what if we need it to edit? Maybe I made a mistake
when I created the item, something like that, right? So I need to put in PUT method. So the put pretty much
takes the new data and then tells the database replaced the old data
with this new data. That's essentially all
that happens in outputs. So to get our endpoint up, I'm just going to say
up dot map ports. And like I said, you
will have updated map. And then the method that you want pretty much
afterwards right? Now we'll put in our
string pattern or our URL. So typically the port looks just like they get in terms of what that
template looks like. So we're getting that same
shopping cart slash id, right? And then we see is
sink and int id. Then we're going to take an object of the type
that we're updating. So in other words, we're going to be updating
a shopping cart item. So that means if you are sending me a record to update
in my database, then obviously you need to
send me the record that you want to replace. That record would that ID, what is the data that
you want to replace? Essentially, that's all that is. So I have to put in a parameter of type shopping
cart, shopping cart. So remember, id is coming
in through the template, but the port to request
generally would send the data not in the parameter is like what it would be part
of the request, the body. So we will see that
in a few int id, shopping cart, shopping carts. And of course we need
some representation of our DB context. And this is just
one big delegate. And then we semicolon
that parenthesis right. Now, what do I want to do? First thing is I want to make sure that whatever you're trying to update
actually exists. If it doesn't exist, then I'll just
really I can't find a record that you're
trying to update. So I'm going to do something
like what I did here. I went to see a weight, the find method, but before that I have to
assign it somewhere. So var lets us see record is equal to look into
shopping carts and find the record with
that ID, right? And actually, let me backtrack a bit
sooner, remove this line. What happens is
that we're going to have multiple things doing. So unlike the other ones
where there were one-liners, we're going to have
a number of things doing so our delegate really can't just allow us
to put in multiple lines. So I have to put in curly braces instead
of this delegate body. And I'll just close that up. And then inside of
these curly braces, I can now put in the various
lines of code that I want. So here I can see var record is equal to db dot shopping
carts that find async. And then I can end up
with the semicolon. Alright? So it's a different
style of coding. It's a bit more functional
than procedural, like you'd probably
be used to both. It's just a matter of
practice making permanent. So I wanted to see
if a record and generally I like to check
for the negative first. So if the record is null
and you can check for null by seeing equivalent to null or you can actually see is null. That one would probably
read a bit better. If it is null, then I'm just going to return
results, dots not found. I couldn't find the record that you said you're
trying to open it? No. If it gets beyond that part, then we're going to
want to do this update. So I went off to see a record
dots and then I'm going to have to pee and stick in legal
through each method sorry, each property that came
in and not be at it. So record here is
what's in the database. Shopping cart here represents the incoming shopping cart data, the payload, the request
body with the new data. I don't know if you
change the name. I don't know what to change. So to be on the safe side
after update everything. So if you're used to SQL and
update statements in SQL, you know that you have to
change every single thing inside an SQL statement
just to be sure, right? So it's picked up, is picked up. What else did we have? We have we had quantity. I don't think we have anything that's global.
Can't update Id. Alright, we would want
to update the record ID. So after we've made
all of those changes, what we would want
to do is I'll wait, db dot save changes a sink, then we can return. So whenever we do an HTTP request that doesn't necessarily have
anything to return, what we see is no content. So it's Solon's bud. I'm not going to return. Okay, but after
update operation, I don't really need
to give you back the data you just give me
because you already have it. So I would say no content, which pretty much means that
I have nothing to return. But this is a tool
for, there we go. So it basically says, I have
nothing to return to you, but your operation was good. Everything is good to go
at that point, right? So let us test out
our operation. So I'm just going to
run without debugging. And swagger is on the ball
with the color-coding, so it gets in blue and then
we have are putting orange. I can try it out. No one. I will see you in the ID
goes in the parameter. I was also seeing that the rest of the data goes in
the request body. So here's where I say I want to update record with the ID1. And then what is the data
I want to send over? So these are risky things. And in my, in my full
end-to-end API course, I do point out the
dangers of having certain fields exposed in
life PUT and post endpoints. You can go through that course. But once again, I'm keeping
it simple here, right? But typically you
would want to take that ID value or you can write the code like we did to not a colon for the id
value being imprisoned. So let's say I change
these values, right? So record with the ID1,
lets us look at it. No. So if I go to the get, try it out and say Show
me record with the ID1. It is going to show
me ID1 item soap. So quantity three
big top is false. I'm not going to change
anything in this request body. This request body represents
the same fields and corresponding values
that would expect for our shopping cart entry. So if I press Execute, what will happen is that to
all four it was successful. And if I go back and retrieve
that record with ID1, I'm just going to
execute this again. Now we're going to see
it looking just like what we just sent up
as a request body. So if I want to change this to hum and pick up
ten homes, right? Executes. All it does is take
everything here. And the idea is that
it's just going to replace what's in the database. There we go. Alright, so a few things about
what Entity Framework did. One, when we retrieve
our records, we actually retrieve it. And there's this feature
called trucking that is enabled in a retrieve it
like this with trucking, any changes that
you make to any of the properties are the values. You can just call Save Changes. And it will automatically
know that this was changed because he was
tracking the values. So once this line runs, it knows that this record
is no quote unquote dirty. So when you see if GnG
is look at this record and execute the changes
that were made, pretty much that's
what happens, right? There are other ways
because you can retrieve data with no tracking. So what happens is that when you have
hundreds of records you probably don't want to
tracking because it can cause performance issues. So you would see persons put on as more tracking
their queries. But that is usually more for applications that reach
that maintain state. So far an API there
is no really, There's not really any
state that is retrieved. And that's just a
teachable moment. I'm just helping you to understand what
tracking is and why this was able to
work just like that without us calling
db dot update. Alright. So that is pretty much it for us putting
together the output. So you can think of all the outputs that
you may want to setup. But for no, that
one is good enough.
8. Explore POST Method: Our guy. So let us look at
creating our post method. So just to do this
simply and quickly, I'm just going to copy the puts method and
paste it again. And we're going to
see a mop post, post. This endpoint is not willing
to have any parameter on it. So it's just going to
be slash shopping cart. And then we are going to take this spirometer and we're only waiting for the payload in
the request body, right? So that shopping cart
object is what we expect to get two Editor database
in terms of the code, we don't have to do any checks. All we need to do is add this shopping cart
item to the database. I'm just going to say
db dot shopping cart. Or I could actually
just say db dot odd. And then we just give it
that shopping cart object. And then we save changes. Then what we're going to return would be a Created response. So created would have
a tool one, right? Tool one is the status code. So created. You could also say
something more like created out to route. So you can give me the root name and some other fancy stuff. But I'll just keep
it simple, created. And then we're just going
to give it back some data. So it knows that it's created
at slash shopping cart. So the response will have the endpoint slash
and then the ID. So basically what we're
seeing is if you go to slash shopping carts with the
shopping cart dot ID, then you can find that method, find that data, sorry. Then we return the
actual object. So essentially created
and we're telling it the string where it can
go to see the created data. And then that is the
actual data payload alongside the route
that you could go to. And that's essentially it. So let us test this old. So color-coding is
that it once again, we have our post method here. Try it. Oh, and I shouldn't be providing an idea
when I'm creating, but we already discussed that, that we're just keeping
things simple here for now. Let us try another
item. This time. I want cereal, and I want
two boxes of cereal. And it hasn't been
picked up as yet. So when we execute this, that represents our
objects that were then sending to the database
and C gets created, it gets the ID for and
everything is there. So if I do a get
all and execute, then I will see 123 and our newly created
item, item four. And that's really it
for all post method. So once again, we
waited for the payload, which then got what will cause de-serialized into this object. And then we added it to the database and then
we save changes. So what you would see with Entity Framework
Core is that you could actually say db dot add, and add takes some type. It doesn't really know what
type might be attempted. But as long as it is off
the entity or as long as it can find it in the DB context and you
won't get any problems. You would also see db dot and then the specific table
and then that ad, right? So I'm just showing
you that you could do either one really db
dot add shopping cart. And then it knows is just
save the changes and it will find the appropriate
table to put in the data. And we've seen that that works. So that's it for
our post method.
9. Explore DELETE Method: We're back and this
time we're going to be looking at the delete method. So we're going to do map delete. Once again, I'm going
to take our PUT and then we're just going to
retrofitted to be Delete. Alright? So I'm sure you know what it is, but I know it doesn't
really matter the order that you put the methods in. It's not went off
faked which one gets executed first
sic on our third because it's not matter
It's not a matter of the chronological order or
the order of the method is just which one is
requested at which 0.1 thing I should
point out is that you should never have two of the same methods with
the same endpoint. So let's go back to the good. We have multiple gets, but notice that each one has a different endpoint
address, right? So if I had to get methods with the same slash shopping carts, that would cause a problem. But because I've mapped
get an Nmap posts, where is it to get
it right? My post. And both of them how
slash shopping cart, it doesn't cause a crash because one is get on, one is post. So if I forgot to
change this and add the two Map puts with the
same end point value. It would just cause a problem. Let's actually look at that. It's good to see these
errors so that we know what we're diagnosing when we're
faced with these challenges. When you do that and
solve your loads, it will just tell
you hate fail to load is not giving any
more data than that. If you get something like this, go back and check and make sure that you're not
making that mistake. So a simple fix here
is to say map, delete. And it's going to have to retain the same endpoint because
we do want shopping guide. I will do need the ID of
what we are going to delete, what we don't need, however, is the data that we
are going to delete because we can always use
the ID to find the record. So here we get the record. If it is not found, we return not found. And then what I'm going
to do is just say db dot. It would be db dot remove. There we go. Sometimes
I forget these things. So db dot remove and we would remove the record
that we found with that ID. We save changes, so
I just press Save. And what happens is that
there's a feature in Visual Studio 2022
called Hot Reload. So that's that fireball here. So you can actually
enable that when you save it does a Hot
Reload automatically. It might prompt you
like it's prompting me. But you can always
just tap hot reload. Then if he can't just reload it, you can just say rebuild
and apply changes. And it will do what
it needs to do in the background while you are still running without debugging. And when you're running
without debugging, you would have this
console window open. So sometimes you
might try something, I'm just not working properly. Just check for the
console window. You might need to close
it and then start over. Either way, Hot
Reload allows us to just reload our Swagger doc. I know we're seeing or
delete endpoint properly. Then if I try it out
and then try to delete a record with the ID for which is the one
we just created. And we execute that. We see, we're returning
that all content. So delete is another
end point that you can return no
content for, right? It's perfectly fine. The console window, while
we're in development mode, you would see those
queries being spit out on this in the console. And that could be
useful for you to see what gets generated when you run these EF Core
commands right foot, although we don't necessarily
need to focus on that. And at this point, we have our crowd
API up and running. Now when we come back, we'll
just clean up our code and make this look a
bit more presentable.
10. Test API with Swagger Doc: Alright, so let's get back on it and let us test this out. So I'm just going to run without debugging those a
bit more quickly. And we're just going to use swagger tool to test this API. And now an alternative to
Swagger would have been like postman or something
similar to that. But saga is capable, so we'll just use it right now. So when we expand our get, that implies that we'll
be getting back up. Collection will see the sample, the sample object of what
we'll be getting back. And notice the square braces, the depicts that it will
be an array of objects. Let us take, try it out and execute which point it actually goes on
queries the database, and there are all of the sample cars that we
would have entered right? Now if I tried to get by ID, let me try that one. So try it all. It says
give me the idea, I'll give it ten. And we get back the 200 response with
the car with the ID ten. I try it with a 100. I don't have a 100 cars. So this time I get
bought that for all four because it
couldn't find that car. Bad idea, right? You can pay attention to
lead the response URLs. Namely the, this is what we call the base URL because
that's the server. And then this would be the path, and then that will be our
id value going over, right? So it's good to pay
attention to these things because when we're writing
code to interact with the API, we have to mimic these kinds of URLs so that verifies that
all gets by ID works. Let's try the Pulitzer. If I tried to modify
car with ID1, Let's make it into a string, string,
string, string, string. So let me first
retrieve the car with the ID1 so we can see
what it looked like. So that is the car with the ID one and we take our
quick copy of it. It's a Honda Fit, Vinny's ABC. Now, when I run this, I notice I would have to put in all the details and
tend to update width. So if I leave the defaults
and click Execute, it's going to tell
me no content, which means it was successful. If I attempt to retrieve
this car again, then I'm going to see
that it is not working. Let's set the cord. And my bud. This is, this is my silly mistakes. So actually mixed up the assignments I
should've been assigning. Record the value is
coming in through car. So I apologize for that. Makes up I have on my
hot reload on Save, so I should be able to just
go back and try again. So that's executes. We're seeing one Honda
Fit and everything. And then when I tried
to execute here, I get the tool for. So no, I'm seeing, there we go. So now we're seeing everything
changed to a string. My silly mistake guys. So that works. And that's why
testing is important. Alright, so let
me just revert to my original payload and
then execute again. And then we can
verify that we now see the original data,
right, looking good. Then the final one
is the delete. So which one would
I want to delete? Let us still the I I'm not I don't want to see what
kind of car I'm not fond of. What I'm going to delete. The one that I'm
least fond of in this list would be the
car with the ID four. It'll be too small for my taste. So there we get
the tool for that suggests that it was
completed successfully. So if I go back and execute, there is no longer a
car with the IED four. Just like that, our code works.
11. API Review: All right guys, So the
last listen left us with our working API that does
basic crud operations. What we don't want
is access code. We don't want the
forecast quotes. I went to remove that. I'm also going to remove
Record at the bottom. And right now, all we have is the code that we know
we absolutely need. Know there are different
ways that you can organize your minimal API
because you could create methods that you
obstruct the code to. You could put it in a different class and then
call it as a middleware. There are number of
ways to do that. I'm really not going to get into all of those ways, right? No. But at least at the
end of this exercise, you will know how
to create API using the minimal coding
style that can do crowd against the database.