Okay.
So now we're on section 13, the final section in this training course.
And we're kind of going to go back to development mode at this stage.
So we've got our application deployed on the internet.
Great.
We're going to leave that deployed.
It's now out there and we're going to add a new feature into our application.
So we're going to go literally back to development mode now.
So I'm going to close up the other tabs.
We don't need to worry about those.
And I'll put it in dark mode I think I prefer this mode.
And we're going to add an admin feature and effectively an inventory a small inventory, a very simple
inventory.
We're not going to go too far with this, but I want to demonstrate the Crud operations that we haven't
really covered yet on this training course, and it will give me an opportunity to look at other things
that we've not seen yet, and also take a look at roles in our application, how we can give one user
additional access to additional features that are not available to normal users.
So let's go back to VSCode and let's close everything down in here.
And the first thing we'll do, actually, and we'll do this from the command line, is we'll come into
our terminal.
I'll just clear this window and I need to go up to the solution level four list.
So please be inside your solution level folder.
Now our main branch.
And by the way, I often get asked this.
How come I see this on my terminal window?
And possibly you do not.
I'll just mention it very briefly now.
And it's called oh my z s h.
It's a terminal enhancement and it is available for Macs, the one that I'm using, of course, but
I believe there is a version of this available for windows as well.
But just search for Oh My Zsh if that's something you would like to implement on your operating system.
I do like it because it does give us information about git, and it does come with some a few other
tricks as well.
It's quite a useful utility, but currently I'm inside the main branch now.
We know from what we did in the previous section that when we deploy our code to GitHub, then that's
going to kick off a workflow that then deploys that code to Azure.
Now, when we're adding a new feature, we might not want that behavior.
In fact, we definitely do not want that behavior because we'd like to test our code before it is deployed
and make sure everything's working before we deploy it to Azure.
So our first action here is going to be to check out our code into a new branch.
So if we do commit our changes, we do not deploy it to the main branch in GitHub, which we know kicks
off the workflow.
So we'll use git checkout and we'll use dash B to create a new branch.
And we'll call it inventory and press return.
And now we've switched to this branch.
And all of our code changes are going to be on this branch, not the main branch.
So we can deploy our changes to GitHub without them being deployed into Azure.
So our CD back into the API.
and we should still have our SQL server running.
We should still have everything available to carry on in development mode, and I'm just going to use
dotnet watch to start the application in development mode.
And this should work without any issues.
And great, that looks fine.
So I'll also go across to the tab that I'm using for the client.
And we'll also run this in development mode as well.
And I'll say npm run dev and great our application is running.
And if I go back to the browser then I should be able to refresh this page.
And we're getting our products from our database.
Again, everything is as it was before.
So we're going to be creating some functionalities specifically for an admin user.
So let's just go across to postman and inside section 13.
Then we've got some requests inside here.
This one to log in as admin.
So I'll click send on this and we get the 200 okay.
And if we go and get the user info for the admin and click send, then we can see that the admin user
is in the admin and the member roles.
Specifically, we're interested in the admin role here so that when we do create a product, then we're
going to send up that cookie that has the admin in that particular role.
So let's go to our code and we're going to create a DTO to receive the product information when we create
a new product.
So I'm going to come into Solution Explorer.
We're going to work on our.
Net side of things first.
And if we go to Dtos let's just right click say new File.
And this is going to be a class and we'll call it Creates products DTO and press return.
And inside here in fact let's open up our products entity and the product CS.
And I'm just going to copy most of these properties inside here the name, description, price, picture,
URL etc. and just paste it into our DTO just to give us a bit of a head start here.
Now we're going to need the name, but instead of using required here the required operator, I'm going
to rely on data validation inside here.
So I'm going to use required from data annotations for the name because this gives us the better output
when it comes to validation.
But I'm going to initialize it to string dot empty.
And this data annotation when this is used means that it will not accept an empty string for the name.
It will be required and I'll do the same for the description as well.
I'll just make this one required and again give it the string dot empty for the price will also make
this required.
And because it's a price, we don't want this to be less than zero.
Of course we don't want to pay people to buy our products.
So we're going to specify a range.
This is how we validate a number.
And we could say for example the minimum is.
The first parameter here is 100 which equates to $1 in our product world.
And we'll also specify a maximum.
And we can use double and positive infinity, which is the maximum possible value for a type of double,
which is a very, very, very large number for the picture.
You, Earl.
Now, we don't have the functionality yet to do anything with this, but we will send it up as a URL.
So we'll specify required, and we'll just have to manually put in a URL for the early stage of what
we're doing here.
And again we'll specify string.empty for this as well.
And then for the type and the brand we'll just make these required as well.
So required and required.
And we'll also make the quantity and stock required.
And once again we'll just use a range for the validator for this.
And we'll say the minimum allowed to be in stock is zero.
And the maximum we'll just say 200.
Just some random arbitrary number for the maximum number in stock.
So next we'll go to our products Controller.
And we're going to add a new endpoint inside here to create a product.
Now inside here there's no authorization or authentication going on inside here.
We want anonymous users to be able to get the list of products and an individual products and the filters.
But below this we're going to create a method to create a new product.
And this is going to be an HTTP post.
And above this we're going to specify that we want this to be authorized and not just authorized for
but for specific roles as well.
So we're going to specify roles equal to admin.
So Bob will not be able to access this endpoint.
But admin who is in the admin role will be able to access this endpoint.
And we use public async task that's going to return an action result of type products.
That we get from our own code not from stripe.
And we'll call it create products and we'll pass in our create product DTO and call it product DTA.
And inside here we effectively need to create a new product from the DTO.
And the way that we've been doing mapping code so far is we'll say var products and then specify a new
product.
And then we'd need to populate each of its different properties with the name which we'd set to product
DTO dot name.
And then we'd need to go through each one individually until we have a product.
I'm not going to do it that way this time, but I'm just going to leave that in as a placeholder for
the time being.
We'll then use our context and say products, Dot adds.
And we'll pass in the product that we've created, which isn't complete yet, and then we'll use the
same technique we've been using so far to update our database.
So we'll say var results and then equals await and context dot save changes async.
And check that the number of changes is greater than zero if results, which equates to true, then
we're going to return a created at action result, and we'll use the name of and we'll use Getproducts.
And this takes an ID as a parameter.
So we need to specify new.
And then in curly brackets we say id equals product.id.
And then we can return the product from this.
And if it's not saved successfully into our database we're going to return a bad request.
And we'll just say problem creating new products.
But we've got an error.
And I wanted to take a look at a different way of mapping properties from one object into another object,
so that we don't have to write that tedious mapping code.
And what we'll take a look at next is the alternative approach.
And next we'll take a look at adding automapper into our application.