Okay, hopefully you took a look at these methods and saw how far you could get with creating the logic
inside here.
I'm going to go through this anyway.
The idea of that was just to get you to have a think about what we might need to do, and maybe give
it a go as well.
The create basket, all that part.
We haven't really covered what we're going to do with that.
So in terms of returning the cookie etc..
So we'll cover all of that in this lesson anyway.
So the first step is to get the basket.
And we've got a couple of items here where we need to get the basket for the add and remove items.
So we'll make this a reusable method.
So I'm going to say var basket equals and I'll just say retrieve basket as the name of the method.
And this is going to need to be an async method because we're going to make a call to our database.
So I'll use await inside there as well.
Now we don't need any parameters or arguments for this method because we're going to get the basket
from the cookies.
So I'm just going to put my cursor inside there and generate the method to do this, and I don't like
its position there.
I'm just going to cut this and put it below the delete method.
So inside this method then to retrieve the baskets we are going to return a basket from this.
So I'm going to specify task.
And inside the task I'm going to specify basket.
But we may or may not have the basket from this.
So I'm going to make it optional so that we can return null from this particular method.
And then we'll just check for the existence of the basket in the method where we use it.
So from here we're going to return await and context dot baskets.
And we need to include the items.
So I'll say x goes to x dot items.
And we'll use let include and say x goes to x dot products.
And then we'll use first or default async.
And we'll specify x goes to x dot baskets id.
That's equal to the request Dough cookies, and in square brackets we're going to have the basket ID
pretty much the same method we used above actually.
So we can also in this case use the same method here.
And instead of using all of that, we can just use a weight and retrieve baskets up here as well.
And then take this line and copy it.
And well we've already got it in the add item to basket.
And then we can go back down to our add item to basket.
So we need to check to see if we have a basket.
And if we do not we're going to need a method to create a basket.
So we can use an if statement here.
And we can check to see if the basket is equal to null and then create the basket.
But I just want to demonstrate another shorthand way of doing such a thing.
So we can specify basket.
And then we can use double question mark which will check it for null.
And if it is null then we can assign In basket to a method that will call create basket.
And what we return from this is going to be a new basket.
So if the basket is null, then we're going to set it equal to what this returns, which is what we're
about to create now.
So I'll just put my cursor inside this method and generate the method.
And then once again I'm just going to cut this and reposition it below the endpoints.
So we've got our methods for the logic separate at the bottom here.
Now this one has automatically generated the question mark there.
But we do not want to return null from this.
We do want to return the basket from this.
We want to ensure it has been created when we do this.
So inside this method we will create a basket ID.
So I'm going to say var basket id equals.
And we can use Guid and then say new guides and open parentheses.
And because we want this to be a string instead of a Guid object, then we're going to use the two string
method on this.
And we're going to create some cookie options because we are going to return this as a cookie.
So I'll say var cookie options equals new cookie options.
And inside here we're going to specify that this cookie is essential.
And we're going to say true because users have the ability to turn off cookies or something along those
lines.
And we want to say hey, for this particular cookie it's essential to the operation of our application.
And basket functionality is essential.
So even if when they see that cookie banner, which is quite prevalent nowadays in many websites and
they say, no, I don't want any cookies going on, this one would still be usable inside the application,
and we're going to give it an expires property equal to date time dot now.
Or let's use UTC now in our application to be consistent with the date times, no matter where it is
in the world, UTC is a standard time zone for the entire planet, so we'll use that rather than the
local version, which would be datetime.now.
And then we'll specify add days and we'll just pick an arbitrary number of 30 for this, that that's
how long this cookie is going to survive for in the user's browser.
If they don't do anything to update it, then we're going to specify response.
So we do something with our HTTP request response.
We're going to say response dot cookies dot append.
And we're going to specify baskets id and then pass in the basket ID.
And then as a third parameter we're going to pass in the cookie options.
Now here once again is your string warning.
Because strings are easy to make mistakes with.
And we don't get any compiler warning.
So please do double check your usage of basket ID and ensure it matches everywhere else we've used it
inside here.
Following this we can specify var baskets equals new basket.
And all we need to do when we create a new basket is provide the basket ID and set it to the basket
ID we've created above.
And we're not getting any warnings here, which means we have met the requirements for creating a new
basket.
Following that, we can tell Entity Framework to start tracking this basket.
And the way that we do that, we say context dot baskets, dot ads and pass in basket.
And then we can return the baskets from this method.
So at this point we're doing nothing with the database.
We're simply asking Entity Framework to track this new basket in memory.
And if we go back up to our ad basket item then now our basket is either the one we've got from our
database or it's the one that we've just created.
So then we need to go and get the product that we want to add.
And we've got the product ID here.
So let's go to the database again and we'll specify var product equals Awaits and context dot products.
And for this one, because we want to get the product by its primary key, effectively, we can actually
use the find async method.
This particular method in Entity Framework only will find an entity with the given primary key values.
If we want to get an entity based on one of its other properties, then we have to use Firstordefault
or single or default, but we can use find async if we do know the primary key ID of that entity.
So we can use the product ID inside here to find it.
Now we have no guarantee that that product exists in the database.
So this product could be null.
So we need to check at this point.
And we'll check to see if the product is equal to null.
And if so then we're going to return a bad request at this point.
And we're just going to say problem adding basket to or problem adding item to basket would make more
grammatical sense.
So with in the last section, we've dealt with handling HTTP response errors.
And we know what's going to happen if we do return a bad request.
At this point, that's going to pop up a toast to the user to notify them that there was an issue with
trying to add this item, because if we don't have the product in the database, we cannot add it to
our basket.
Of course, the next step then is to add the item to the basket.
And we created a method inside our entity to do this.
So we can specify basket add item.
And this takes two parameters.
It takes the product and it takes the quantity.
So we can pass in the product and the quantity inside there.
And then in order to update our database we do need to save our changes into the database.
So we're going to check this as well to make sure that something has been updated in our database.
So we'll use var result then say await context and save changes Is a sink.
So all of the changes that have been saved in memory, perhaps we've got a new basket that we're creating.
Perhaps we've added something to that basket.
Then all of those changes get saved inside this method.
Now, the way that this works with our Dbcontext and Entity Framework, I mentioned earlier that this
uses a couple of patterns.
It uses a repository pattern and a unit of work pattern.
And the idea, the big idea with the unit of work pattern is that all of our changes are tracked.
And then if one of those changes fails, then they all fail and everything gets rolled back to the state
that it was in before we started making changes.
But if they all succeed, then this save changes method will succeed.
So everything inside here is effectively a transaction and transactions.
Either all the changes have to succeed or none of them succeed.
and that's what we really try and achieve when using the unit of work pattern.
But that's already included with Entity Framework and that dbcontext then we can check the results.
And the results, by the way, is going to be an integer.
If we take a look at what this actually returns, then this returns an int.
And this int represents the number of changes that were made into our database.
So all we need to do to check that something is changed in our database is just make sure that number
of changes is greater than zero.
It doesn't matter if it's one, two, five, 50 changes based on what I was saying earlier, if one
change fails, they all fail.
Then we only care if more than zero changes have occurred in our database.
So this will result in true if the changes are greater than zero.
So we can specify if results.
And we're effectively checking to make sure the boolean is equal to true if we just say result that
is effectively equal to saying this.
But we don't need to specify double equals true.
There we can return a created at action result that's going to return to us a 201 and a created action
results will return the thing that we're going to return.
I did mention we're not going to return the basket earlier, but I think we will return the basket as
well at this stage, even though our client doesn't actually need it, because we can handle the changes
locally on the client.
For this example, whilst we're developing our API, I think I am going to return the basket as well.
So the created an action.
It also returns a location header of how to get the thing that's been updated or added.
So we want in this case we want to return the get basket and we return a location header with the response
which will take a look at when we test this in postman of where to get the basket from.
So that's going to be localhost 5001 API forward slash basket.
And that would retrieve the basket.
And that's the location header we want to send back with this response.
Don't worry if that's not 100% clear because it will be once we test this method.
So we give it a name of get basket.
This is the action when we say created an action, this is the action that contains the location, the
endpoint of how to get the basket that has been updated.
And then in the second parameter, we can just pass in the basket as the thing that we are going to
return.
Now if results is false and not true, then we will return a bad request because we didn't save the
changes into the database.
And I'm just going to say problem updating basket for this one.
So now that we've got something some logic in our code and we've got our controller endpoint, what
we'll do is we'll take a look at this through the debugger next so that we can see what's going on as
we're adding an item into our basket.
And we'll take a look at that next.