WEBVTT

00:00.020 --> 00:03.680
Okay, so we're getting our orders back and we've got the ability to create an order.

00:03.680 --> 00:06.440
And now we'll take a look at shaping the order data back.

00:06.470 --> 00:08.630
It's not too bad, but it could do with some improvements.

00:08.660 --> 00:11.300
Obviously we've got an issue with the order items here.

00:11.300 --> 00:13.880
We've got an issue with the order status.

00:14.270 --> 00:19.670
And perhaps I would like things to be organized in here slightly better, especially if I do take a

00:19.670 --> 00:21.680
look at the one with the order items.

00:21.680 --> 00:24.920
We've got a lot of nesting going on inside here.

00:24.920 --> 00:28.970
That's not particularly helpful when it comes to using this data in our client.

00:28.970 --> 00:34.520
So we will go back and we'll shape our data from our order controller.

00:34.550 --> 00:38.390
Now we did something like this before with our basket extensions.

00:38.390 --> 00:45.620
And we created a method to effectively map the properties from one thing to another thing.

00:45.620 --> 00:48.380
And we'll do similar for our order as well.

00:48.380 --> 00:53.510
So that means creating dtos something to shape the data into.

00:53.540 --> 01:00.810
And I'm going to create a new file which is going to be a class, and I'm going to call it order DTO.

01:00.840 --> 01:04.470
And I'm also going to create another class inside the DTO folder.

01:04.470 --> 01:08.250
And this is going to be for our order item DTO.

01:08.820 --> 01:15.000
And let's go and grab the order Entity code, which might be helpful.

01:15.000 --> 01:16.590
And save us a bit of typing.

01:16.590 --> 01:26.490
And I'll copy all of this into my clipboard and paste it into the order DTO.

01:27.780 --> 01:30.630
And let's remove some of the tabs from the top here.

01:33.390 --> 01:35.100
And I've lost the order DTO.

01:35.100 --> 01:36.900
So let's open that again.

01:37.740 --> 01:41.850
And let's paste in the properties from our order inside here.

01:41.850 --> 01:44.490
And we'll just see what adjustments we might want to make to this.

01:44.520 --> 01:46.890
I'm going to keep the shipping address as shipping address.

01:46.890 --> 01:47.940
That's okay.

01:48.150 --> 01:51.810
The order dates I'm going to remove the equals date time.

01:51.810 --> 01:55.620
Now because this is a DTO the order items.

01:55.620 --> 01:57.540
That's going to be a list.

01:59.310 --> 02:02.400
Of order item DTO.

02:05.010 --> 02:11.070
The subtotal delivery fee discount that can stay the same and we won't send back the payment intent

02:11.070 --> 02:13.350
ID we don't need that on the client.

02:13.380 --> 02:18.990
The order status will return as a string and we'll remove its initial value.

02:19.020 --> 02:25.050
And the payment summary will just keep the same as well inside the order item DTO.

02:25.680 --> 02:27.210
Let's just add these in manually.

02:27.210 --> 02:34.050
We'll have a proper it's an int that's going to be for the product ID we'll have a prop that's a string

02:34.050 --> 02:35.340
for the name.

02:36.120 --> 02:42.150
We'll have a prop that's a string for the picture URL.

02:42.660 --> 02:45.960
We'll have a prop that's a long for the price.

02:46.260 --> 02:49.890
And we'll have a prop that's an int for the quantity.

02:50.370 --> 02:57.820
And let's just make this required and we'll make the picture URL required as well.

02:57.850 --> 02:59.770
And I've got an issue in my order DTO.

02:59.800 --> 03:01.000
What did I do here?

03:01.330 --> 03:04.360
And looks like I've lost some using statements.

03:04.360 --> 03:07.090
So I'll just add the order aggregate in there.

03:07.870 --> 03:13.960
And the order items I'll just make this in fact because it's a list I'll just make this square brackets

03:13.960 --> 03:15.400
to initialize that.

03:15.400 --> 03:21.190
And for our order status I'll set this to be required as well.

03:21.940 --> 03:22.720
Okay.

03:22.930 --> 03:28.810
So if we refer back to what we did in our basket extensions, just to give us an idea of where we're

03:28.810 --> 03:34.990
going with this, we need to write this kind of code to shape effectively our order into an order DTO.

03:35.020 --> 03:41.140
Now, this code is a little bit tedious to write, and there is tools out there to help us with that

03:41.140 --> 03:42.130
called Automapper.

03:42.130 --> 03:45.850
But I'm going to stick with doing this using an extension method.

03:45.850 --> 03:51.940
And we will take a look at Automapper a bit later when it comes to the Crud operations, because it's

03:51.940 --> 03:52.990
more helpful then.

03:53.020 --> 04:00.640
But some developers don't like Automapper, and I'm going to keep the majority of examples to not using

04:00.640 --> 04:01.720
Automapper.

04:01.750 --> 04:09.580
And inside the extensions, let's create another extension class and I'm going to call this well let's

04:09.580 --> 04:13.750
select class and I'll say order extensions.

04:16.090 --> 04:20.620
And inside here once again we'll make this a static class.

04:21.400 --> 04:25.120
And I want to approach this slightly differently this one.

04:25.120 --> 04:28.390
And let's close the others down.

04:28.390 --> 04:29.590
Getting quite busy at the top there.

04:29.590 --> 04:35.080
I'm just going to go back to the orders controller and take a look at what we're doing inside here.

04:35.080 --> 04:44.110
And what we are doing is when we let's pick the get requests and when we return these.

04:44.140 --> 04:49.030
And the reason we wasn't getting the order items is I forgot to include the include.

04:49.030 --> 04:52.270
So I'll just add that in here temporarily.

04:52.270 --> 04:55.070
And what we're doing with these include statements.

04:55.070 --> 04:57.230
This is referred to as eager loading.

04:57.260 --> 05:01.520
So instead of using eager loading we'll use projection.

05:01.520 --> 05:04.640
And I'll demonstrate an example of using projection here.

05:04.640 --> 05:10.850
So instead of including everything from the order items, we only select what we need to from the database.

05:10.850 --> 05:13.520
So let's take a look at how we can configure this.

05:13.520 --> 05:17.720
And inside here we'll have two versions of this.

05:17.720 --> 05:19.970
We'll have a public static.

05:20.270 --> 05:27.230
And this is going to be an I o variable of type order DTO that we are going to return from this.

05:27.230 --> 05:30.680
And this is the one that we're going to use with our query.

05:30.740 --> 05:35.480
And we'll use or we'll give it a name of project two DTO.

05:35.480 --> 05:44.240
And we'll say this I queryable of type order as what we're passing into this we get from API entities

05:44.270 --> 05:52.880
order aggregate and we'll call it query inside here we can return and we'll use query.

05:52.880 --> 05:57.200
And then we'll use select so that we can make use of projection.

05:57.200 --> 06:02.540
And we'll use order as the argument and say New order DTO.

06:02.780 --> 06:05.570
And then inside here we'll open curly brackets.

06:05.570 --> 06:08.120
And then we'll just start mapping the different properties.

06:08.120 --> 06:14.390
So the ID is going to be the order ID the buyer email is going to be the order via email.

06:14.540 --> 06:19.430
The order dates is going to be the order dot order dates.

06:19.460 --> 06:24.650
The shipping address is going to be the order dot shipping address.

06:24.650 --> 06:30.890
The payment summary is going to be the order dot payment summary.

06:31.130 --> 06:35.000
The delivery fee will be the order dot delivery fee.

06:35.000 --> 06:40.820
The subtotal is going to be the order dot subtotal.

06:41.060 --> 06:46.910
The order status is going to be the order dot order status.

06:46.910 --> 06:52.980
And then we'll use the two string method on this so that we get the string value of the enum returned

06:53.010 --> 06:58.380
the total, and I do not have the total currently in my order DTO.

06:58.380 --> 07:05.130
So let's open up the order DTO because I wish to return that as well with this.

07:05.280 --> 07:14.700
So after the discount, I'm just going to have a prop of long for the total and back to our extensions

07:14.700 --> 07:21.780
and then specify the total is going to be the order dot get total to calculate that amount.

07:21.780 --> 07:26.130
And for the order items we'll say order dot order items.

07:26.400 --> 07:29.670
But we wish list to be projected into a DTO as well.

07:29.670 --> 07:40.560
So I'll use select and we'll say item add the arrow and new order item DTO and then open curly brackets.

07:40.560 --> 07:49.200
And we'll have our product ID is going to be the item dot item ordered dot product ID the name will

07:49.200 --> 07:53.470
be the item dot item ordered dot name.

07:53.500 --> 07:59.950
The picture URL will be the item ordered item ordered dot picture URL.

07:59.950 --> 08:00.670
Almost there.

08:00.700 --> 08:08.770
The price is going to be the item dot price, and the quantity is going to be the item dot quantity.

08:08.770 --> 08:15.490
And then we can output this to a list for our order items.

08:15.670 --> 08:18.370
And then close this off with a semicolon.

08:18.370 --> 08:22.300
So that's our mapping code from the order to the order DTO.

08:22.300 --> 08:26.380
And we can use this one in our orders controller.

08:26.410 --> 08:32.320
Instead of using the eager loading here we can specify that we wish.

08:32.860 --> 08:34.240
Instead of this include.

08:34.270 --> 08:37.870
We can specify that we wish to use the context orders.

08:37.870 --> 08:41.410
And then we can use our project to DTO method.

08:41.500 --> 08:45.370
And we're getting an error here because we're not returning a list of orders.

08:45.370 --> 08:50.380
Now we're projecting this Into and list of order dtos.

08:50.380 --> 08:53.020
So we'll just change the type at the top here.

08:53.020 --> 08:57.490
And then that's going to cover the getting of an order.

08:57.580 --> 09:00.940
And we'll just do the same with the get order details as well.

09:00.940 --> 09:08.590
So instead of include there we'll use our new project to DTO and then just do the same and say that

09:08.590 --> 09:11.230
we're returning an order DTO here.

09:11.230 --> 09:15.070
If we go and test our progress on this and looks like I need to restart the API.

09:15.100 --> 09:20.020
So I'm just going to say yes to this and head over to postman and just take a look at the difference

09:20.020 --> 09:24.190
between what we had before and what we get now that we're using projection.

09:24.190 --> 09:32.020
So I'll click send and I get a tracking query is attempting to project an owned entity without a corresponding

09:32.050 --> 09:33.370
owner in its results.

09:33.370 --> 09:36.070
But owned entities cannot be tracked without their owner.

09:36.100 --> 09:42.310
Either include the owner entity in the result, or make the query non tracking using as no tracking.

09:42.310 --> 09:46.850
So when we go and get things from Entity Framework then.

09:46.850 --> 09:49.640
By default it tracks them in memory.

09:49.640 --> 09:55.910
So if we do make changes to them, then when we call the save changes async method, that tracked entity

09:55.910 --> 10:00.320
is then saved into our database because we're projecting this into a DTO.

10:00.350 --> 10:05.150
The properties that we're projecting to don't have a corresponding owner.

10:05.420 --> 10:14.030
So to get around this, what we will do is simply add no tracking for our Get queries when we use the

10:14.030 --> 10:15.410
project to DTO.

10:15.440 --> 10:21.320
So we'll head back to the orders extension, and we'll just append onto list just below the two list.

10:21.350 --> 10:23.930
We'll just say as no tracking.

10:24.830 --> 10:27.230
And that should satisfy Entity Framework.

10:27.260 --> 10:28.850
Let's just take a look at the terminal.

10:28.880 --> 10:30.860
It tells me Hot Reload has succeeded.

10:30.890 --> 10:34.250
Let's give it a chance and I'll click send again.

10:34.250 --> 10:36.380
And this time we get what we're looking for.

10:36.380 --> 10:41.240
So now we should have our data shaped a bit more cleanly and how we want it.

10:41.270 --> 10:48.350
We can see the order items is now no longer nested as deeply, and we can see the order status is pending

10:48.350 --> 10:50.900
and we've got our total inside there as well.

10:50.900 --> 10:55.520
If I check the get order details and do the same thing, then we should have the same.

10:55.520 --> 11:01.040
We should have our well, it's going to be effectively the same because we've only got one order.

11:01.820 --> 11:02.630
Great.

11:02.630 --> 11:04.820
But we've also got our create order.

11:04.820 --> 11:08.840
And if we take a look at what we got back from there, this is not shaped as a DTO.

11:08.840 --> 11:11.420
So we also wish to shape this as a DTO.

11:11.420 --> 11:13.550
But we're not going to project this.

11:13.550 --> 11:20.870
So we need another extension method inside our order extensions just to convert what we have to a DTO.

11:20.870 --> 11:32.870
So below this methods, the project to DTO will have public static, and this one is just going to return

11:32.870 --> 11:41.450
an order DTO and we'll just call it to DTO and we'll pass in this order and call it order.

11:41.900 --> 11:47.490
And we need to return a new DTO with effectively exactly the same code.

11:47.490 --> 11:56.010
So I'm just going to copy what we have in here up and to just before the as no tracking into my clipboard

11:56.220 --> 12:02.130
and I will return and then paste in what I have and just make any small adjustments we need to.

12:02.160 --> 12:08.460
I don't need this extra parentheses at the end there, and just need to close this off with a semicolon.

12:08.460 --> 12:15.840
So that's our code for just making an order and shaping that into an order DTO.

12:15.870 --> 12:20.790
Otherwise, the code is exactly the same as what we used inside the projection one.

12:20.790 --> 12:25.710
So inside our orders controller again let's take a look at our create order.

12:25.710 --> 12:28.260
And everything can stay the same inside here.

12:28.260 --> 12:35.160
But where we're returning our order, let's just use our order to DTO method.

12:35.250 --> 12:39.930
And now when we create a new order, we should get it shaped just like our get request.

12:39.960 --> 12:42.690
And let's give that a test.

12:42.690 --> 12:49.650
So we're going to need a new basket as currently if I get a basket because we've created an order using

12:49.650 --> 12:53.580
this basket, what I should get is 204 no content.

12:53.580 --> 12:54.750
So we need a new basket.

12:54.750 --> 12:58.830
So I'm just going to add an item to the basket which will create us a basket.

12:58.830 --> 13:00.420
So I'll click send on this one.

13:00.780 --> 13:03.840
We've got our basket but it doesn't have a payment intent ID.

13:04.050 --> 13:07.680
So we're going to need to create that payment intent for this one.

13:07.680 --> 13:11.550
So I'll click Create Payment Intent and I'll click send.

13:12.000 --> 13:13.440
And this goes off to stripe.

13:13.440 --> 13:16.980
And it populates the client secrets and the payment intent ID.

13:17.370 --> 13:20.790
And then we can go ahead and create our order.

13:20.790 --> 13:24.150
So I'll go ahead and do that now and click send.

13:24.150 --> 13:27.240
And we get our order back with the ID of two.

13:27.240 --> 13:32.010
And we've got our response shaped just how we want it.

13:32.010 --> 13:33.420
So great.

13:33.420 --> 13:37.380
So that's as far as we can go for the API side of things for the time being.

13:37.380 --> 13:41.820
Next we'll move on to the client side and deal with the orders in there.
