WEBVTT

00:00.020 --> 00:00.380
Okay.

00:00.380 --> 00:04.460
So now we're on section 13, the final section in this training course.

00:04.460 --> 00:08.480
And we're kind of going to go back to development mode at this stage.

00:08.480 --> 00:10.820
So we've got our application deployed on the internet.

00:10.850 --> 00:11.360
Great.

00:11.360 --> 00:12.800
We're going to leave that deployed.

00:12.800 --> 00:17.330
It's now out there and we're going to add a new feature into our application.

00:17.330 --> 00:20.150
So we're going to go literally back to development mode now.

00:20.150 --> 00:23.180
So I'm going to close up the other tabs.

00:24.140 --> 00:26.090
We don't need to worry about those.

00:26.090 --> 00:30.080
And I'll put it in dark mode I think I prefer this mode.

00:30.080 --> 00:39.650
And we're going to add an admin feature and effectively an inventory a small inventory, a very simple

00:39.650 --> 00:40.400
inventory.

00:40.430 --> 00:44.480
We're not going to go too far with this, but I want to demonstrate the Crud operations that we haven't

00:44.480 --> 00:49.430
really covered yet on this training course, and it will give me an opportunity to look at other things

00:49.430 --> 00:56.330
that we've not seen yet, and also take a look at roles in our application, how we can give one user

00:56.360 --> 01:02.900
additional access to additional features that are not available to normal users.

01:02.900 --> 01:08.500
So let's go back to VSCode and let's close everything down in here.

01:08.500 --> 01:15.760
And the first thing we'll do, actually, and we'll do this from the command line, is we'll come into

01:15.790 --> 01:16.840
our terminal.

01:16.870 --> 01:22.630
I'll just clear this window and I need to go up to the solution level four list.

01:22.630 --> 01:26.020
So please be inside your solution level folder.

01:26.050 --> 01:28.000
Now our main branch.

01:28.000 --> 01:30.010
And by the way, I often get asked this.

01:30.010 --> 01:32.800
How come I see this on my terminal window?

01:32.800 --> 01:34.780
And possibly you do not.

01:34.810 --> 01:37.180
I'll just mention it very briefly now.

01:37.210 --> 01:41.290
And it's called oh my z s h.

01:41.320 --> 01:50.500
It's a terminal enhancement and it is available for Macs, the one that I'm using, of course, but

01:50.500 --> 01:54.190
I believe there is a version of this available for windows as well.

01:54.190 --> 02:01.180
But just search for Oh My Zsh if that's something you would like to implement on your operating system.

02:01.180 --> 02:06.640
I do like it because it does give us information about git, and it does come with some a few other

02:06.660 --> 02:07.260
tricks as well.

02:07.260 --> 02:11.580
It's quite a useful utility, but currently I'm inside the main branch now.

02:11.580 --> 02:17.790
We know from what we did in the previous section that when we deploy our code to GitHub, then that's

02:17.790 --> 02:22.080
going to kick off a workflow that then deploys that code to Azure.

02:22.110 --> 02:25.620
Now, when we're adding a new feature, we might not want that behavior.

02:25.620 --> 02:31.260
In fact, we definitely do not want that behavior because we'd like to test our code before it is deployed

02:31.530 --> 02:35.220
and make sure everything's working before we deploy it to Azure.

02:35.220 --> 02:40.410
So our first action here is going to be to check out our code into a new branch.

02:40.650 --> 02:45.960
So if we do commit our changes, we do not deploy it to the main branch in GitHub, which we know kicks

02:45.960 --> 02:46.710
off the workflow.

02:46.710 --> 02:51.690
So we'll use git checkout and we'll use dash B to create a new branch.

02:51.690 --> 02:56.220
And we'll call it inventory and press return.

02:56.280 --> 02:58.020
And now we've switched to this branch.

02:58.020 --> 03:01.740
And all of our code changes are going to be on this branch, not the main branch.

03:01.740 --> 03:06.870
So we can deploy our changes to GitHub without them being deployed into Azure.

03:07.770 --> 03:09.720
So our CD back into the API.

03:09.760 --> 03:12.310
and we should still have our SQL server running.

03:12.310 --> 03:17.500
We should still have everything available to carry on in development mode, and I'm just going to use

03:17.500 --> 03:21.250
dotnet watch to start the application in development mode.

03:22.930 --> 03:26.290
And this should work without any issues.

03:26.290 --> 03:27.790
And great, that looks fine.

03:27.790 --> 03:30.850
So I'll also go across to the tab that I'm using for the client.

03:30.850 --> 03:33.820
And we'll also run this in development mode as well.

03:33.820 --> 03:38.050
And I'll say npm run dev and great our application is running.

03:38.080 --> 03:41.320
And if I go back to the browser then I should be able to refresh this page.

03:41.320 --> 03:43.240
And we're getting our products from our database.

03:43.240 --> 03:47.080
Again, everything is as it was before.

03:47.080 --> 03:51.310
So we're going to be creating some functionalities specifically for an admin user.

03:51.310 --> 03:55.750
So let's just go across to postman and inside section 13.

03:55.750 --> 03:57.820
Then we've got some requests inside here.

03:57.820 --> 04:00.040
This one to log in as admin.

04:00.040 --> 04:03.160
So I'll click send on this and we get the 200 okay.

04:03.160 --> 04:09.940
And if we go and get the user info for the admin and click send, then we can see that the admin user

04:09.940 --> 04:12.720
is in the admin and the member roles.

04:12.780 --> 04:19.560
Specifically, we're interested in the admin role here so that when we do create a product, then we're

04:19.560 --> 04:23.280
going to send up that cookie that has the admin in that particular role.

04:24.060 --> 04:31.020
So let's go to our code and we're going to create a DTO to receive the product information when we create

04:31.020 --> 04:31.740
a new product.

04:31.740 --> 04:33.660
So I'm going to come into Solution Explorer.

04:33.660 --> 04:34.500
We're going to work on our.

04:34.710 --> 04:36.210
Net side of things first.

04:36.210 --> 04:39.330
And if we go to Dtos let's just right click say new File.

04:39.330 --> 04:47.280
And this is going to be a class and we'll call it Creates products DTO and press return.

04:47.640 --> 04:57.720
And inside here in fact let's open up our products entity and the product CS.

04:57.720 --> 05:03.150
And I'm just going to copy most of these properties inside here the name, description, price, picture,

05:03.150 --> 05:09.780
URL etc. and just paste it into our DTO just to give us a bit of a head start here.

05:09.810 --> 05:14.790
Now we're going to need the name, but instead of using required here the required operator, I'm going

05:14.820 --> 05:17.070
to rely on data validation inside here.

05:17.070 --> 05:24.720
So I'm going to use required from data annotations for the name because this gives us the better output

05:24.720 --> 05:26.220
when it comes to validation.

05:26.220 --> 05:29.640
But I'm going to initialize it to string dot empty.

05:29.640 --> 05:37.440
And this data annotation when this is used means that it will not accept an empty string for the name.

05:37.440 --> 05:43.320
It will be required and I'll do the same for the description as well.

05:43.920 --> 05:52.200
I'll just make this one required and again give it the string dot empty for the price will also make

05:52.200 --> 05:53.700
this required.

05:53.700 --> 05:58.230
And because it's a price, we don't want this to be less than zero.

05:58.230 --> 06:01.680
Of course we don't want to pay people to buy our products.

06:01.680 --> 06:03.900
So we're going to specify a range.

06:03.900 --> 06:05.940
This is how we validate a number.

06:05.940 --> 06:08.850
And we could say for example the minimum is.

06:08.850 --> 06:14.190
The first parameter here is 100 which equates to $1 in our product world.

06:14.190 --> 06:16.800
And we'll also specify a maximum.

06:16.800 --> 06:25.120
And we can use double and positive infinity, which is the maximum possible value for a type of double,

06:25.120 --> 06:29.770
which is a very, very, very large number for the picture.

06:29.770 --> 06:30.940
You, Earl.

06:30.970 --> 06:37.150
Now, we don't have the functionality yet to do anything with this, but we will send it up as a URL.

06:37.180 --> 06:45.160
So we'll specify required, and we'll just have to manually put in a URL for the early stage of what

06:45.160 --> 06:45.880
we're doing here.

06:45.880 --> 06:49.180
And again we'll specify string.empty for this as well.

06:49.180 --> 06:54.670
And then for the type and the brand we'll just make these required as well.

06:54.670 --> 06:59.410
So required and required.

06:59.440 --> 07:02.110
And we'll also make the quantity and stock required.

07:02.110 --> 07:05.500
And once again we'll just use a range for the validator for this.

07:05.500 --> 07:11.290
And we'll say the minimum allowed to be in stock is zero.

07:11.590 --> 07:13.480
And the maximum we'll just say 200.

07:13.480 --> 07:18.370
Just some random arbitrary number for the maximum number in stock.

07:18.400 --> 07:21.900
So next we'll go to our products Controller.

07:23.100 --> 07:27.000
And we're going to add a new endpoint inside here to create a product.

07:27.030 --> 07:32.460
Now inside here there's no authorization or authentication going on inside here.

07:32.460 --> 07:39.810
We want anonymous users to be able to get the list of products and an individual products and the filters.

07:39.810 --> 07:44.670
But below this we're going to create a method to create a new product.

07:44.670 --> 07:46.950
And this is going to be an HTTP post.

07:46.950 --> 07:53.700
And above this we're going to specify that we want this to be authorized and not just authorized for

07:53.700 --> 07:55.500
but for specific roles as well.

07:55.500 --> 07:58.230
So we're going to specify roles equal to admin.

07:58.230 --> 08:01.710
So Bob will not be able to access this endpoint.

08:01.710 --> 08:07.080
But admin who is in the admin role will be able to access this endpoint.

08:07.140 --> 08:15.060
And we use public async task that's going to return an action result of type products.

08:17.430 --> 08:20.940
That we get from our own code not from stripe.

08:21.840 --> 08:31.240
And we'll call it create products and we'll pass in our create product DTO and call it product DTA.

08:31.270 --> 08:35.890
And inside here we effectively need to create a new product from the DTO.

08:35.920 --> 08:42.460
And the way that we've been doing mapping code so far is we'll say var products and then specify a new

08:42.460 --> 08:43.570
product.

08:44.380 --> 08:49.840
And then we'd need to populate each of its different properties with the name which we'd set to product

08:49.870 --> 08:51.460
DTO dot name.

08:51.460 --> 08:55.750
And then we'd need to go through each one individually until we have a product.

08:55.750 --> 08:59.440
I'm not going to do it that way this time, but I'm just going to leave that in as a placeholder for

08:59.440 --> 09:00.460
the time being.

09:00.640 --> 09:05.650
We'll then use our context and say products, Dot adds.

09:07.420 --> 09:13.300
And we'll pass in the product that we've created, which isn't complete yet, and then we'll use the

09:13.300 --> 09:16.900
same technique we've been using so far to update our database.

09:16.900 --> 09:22.990
So we'll say var results and then equals await and context dot save changes async.

09:22.990 --> 09:31.770
And check that the number of changes is greater than zero if results, which equates to true, then

09:31.770 --> 09:41.490
we're going to return a created at action result, and we'll use the name of and we'll use Getproducts.

09:42.780 --> 09:45.540
And this takes an ID as a parameter.

09:45.540 --> 09:46.980
So we need to specify new.

09:46.980 --> 09:51.840
And then in curly brackets we say id equals product.id.

09:52.140 --> 09:55.320
And then we can return the product from this.

09:55.350 --> 10:01.860
And if it's not saved successfully into our database we're going to return a bad request.

10:02.160 --> 10:08.970
And we'll just say problem creating new products.

10:09.570 --> 10:10.740
But we've got an error.

10:10.740 --> 10:19.020
And I wanted to take a look at a different way of mapping properties from one object into another object,

10:19.080 --> 10:22.740
so that we don't have to write that tedious mapping code.

10:22.920 --> 10:27.360
And what we'll take a look at next is the alternative approach.

10:27.360 --> 10:31.170
And next we'll take a look at adding automapper into our application.
