WEBVTT

00:00.000 --> 00:00.240
Okay.

00:00.270 --> 00:04.590
Another endpoint that we're going to add is we're just going to deal with the updating of address and

00:04.590 --> 00:10.020
getting an address of a user, as when a user checks out, we want to see if or allow them to save the

00:10.020 --> 00:15.060
address they want to use for shipping, and also retrieve that address when they enter the checkout

00:15.060 --> 00:17.280
if they have a saved address.

00:17.280 --> 00:22.830
So we'll set that up now since we're dealing with our API, and we'll get all of the API side of things

00:22.830 --> 00:25.620
done whilst we're dealing with identity related stuff.

00:25.620 --> 00:29.730
Although this is just a normal thing that we're going to save into our database.

00:29.730 --> 00:36.480
So we're going to create an entity for the address and I'll say new file select class and just call

00:36.480 --> 00:37.620
this address.

00:37.650 --> 00:42.390
And inside here we'll give this its necessary properties.

00:42.390 --> 00:49.650
We'll have a prop that's an int that's an ID we'll have prop that's a string for the name.

00:50.040 --> 00:53.250
We'll have a prop that's a string.

00:53.250 --> 00:55.170
And we'll say line one.

00:55.170 --> 01:00.210
And what we're going to do here really is match the properties that we're going to use in our payment

01:00.210 --> 01:04.570
provider, which is stripe And these are the address properties.

01:04.570 --> 01:09.040
There's many different ways of formatting address fields, but we're going to go for the ones that are

01:09.040 --> 01:12.040
used by stripe and match them exactly.

01:12.250 --> 01:15.670
So we're also going to have a string for line two as well.

01:15.940 --> 01:24.430
And we'll have a prop that's a string for the city, and we'll have a prop that says string for the

01:24.430 --> 01:25.510
state.

01:26.620 --> 01:36.400
And we'll also have a prop that's a string for the postal code, and a prop that's a string for the

01:36.400 --> 01:37.330
country.

01:38.830 --> 01:43.000
And let's see what we need as required and optional properties.

01:43.000 --> 01:45.760
So the name is going to be required for someone's shipping address.

01:45.760 --> 01:47.950
So we'll put the name in as required.

01:47.950 --> 01:50.500
Line one is also required.

01:50.500 --> 01:55.660
Line two we're going to make optional as that is how it is in stripe.

01:55.660 --> 02:01.060
They don't have to supply line two of their address and not every address has a second line.

02:01.270 --> 02:03.740
The city will be required.

02:03.890 --> 02:06.740
So I'll just copy this.

02:06.770 --> 02:11.600
I'll ignore whatever warning that is for whatever button I accidentally clicked that caused that error

02:11.630 --> 02:16.850
or warning, and I'll just put in required for the rest of these.

02:16.880 --> 02:20.900
Another thing that I'm going to do that's slightly different to what we've done before.

02:20.930 --> 02:25.880
Once I've got required in here, is we're also going to treat the postal code differently, because

02:25.880 --> 02:32.420
the way that stripe returns this information is different to how we store it in C sharp.

02:32.420 --> 02:39.380
And it's different enough because it uses an underscore in between the two words here for postal code.

02:39.410 --> 02:42.440
We're going to use a slightly different approach for this one.

02:42.440 --> 02:47.390
And we're going to use an attribute called JSON property name.

02:47.390 --> 02:54.530
And in parentheses and quotes we're going to specify all in lowercase postal underscore code.

02:54.920 --> 03:04.060
The idea being is that when we return an address and the JSON serializer formats our address into JSON.

03:04.090 --> 03:06.730
Then it's going to use this as the property name.

03:06.760 --> 03:13.570
Also, when we update an address, it's going to look for this property that has this formatting for

03:13.570 --> 03:14.680
the property name.

03:15.490 --> 03:21.940
And it will bind to this even though it doesn't match the name I've specified here, which is in C-sharp

03:21.940 --> 03:23.800
conventional format.

03:23.830 --> 03:28.900
Another thing we'll do that we haven't looked at before is I don't really want to send back the ID of

03:28.900 --> 03:29.410
the address.

03:29.410 --> 03:32.080
I need the ID in the database, so fine.

03:32.080 --> 03:36.340
But I don't want to send this property back as part of our JSON response.

03:36.340 --> 03:40.660
So another thing we can do inside here is we can use JSON ignore.

03:41.050 --> 03:44.620
And when we do ask for an address we're going to get all of these properties.

03:44.620 --> 03:47.950
But we're not going to get the ID we just don't need it.

03:47.950 --> 03:52.090
And our address is going to be related to our user.

03:52.090 --> 03:56.830
So we're going to have a 1 to 1 relationship between a user and an address.

03:56.830 --> 03:59.500
We're not going to allow the user to solve multiple addresses.

03:59.530 --> 04:04.870
Obviously you do see that kind of thing in many e-commerce apps, and you could go that far if you wanted.

04:04.880 --> 04:05.870
It's not a big deal.

04:05.900 --> 04:10.490
But for this example, on this training course, I'm just going to have a 1 to 1 relationship between

04:10.490 --> 04:16.370
a user and the address, and I'll open up the user dot CSS.

04:16.370 --> 04:20.420
And inside here we're going to effectively extend our user.

04:20.420 --> 04:31.220
And we're going to use public int and have address ID and prop address.

04:31.760 --> 04:35.510
And we'll specify address as the name of that property.

04:35.540 --> 04:40.100
Now for both of these I'm going to make them optional because it's not going to be a requirement for

04:40.130 --> 04:45.920
a user when they sign up or when they use our app to ever save an address, they can always just enter

04:45.920 --> 04:47.840
the address manually in our checkout.

04:47.870 --> 04:52.700
We won't force them to save an address, but they can do if they want to for convenience when they come

04:52.700 --> 04:53.810
back the next time.

04:53.840 --> 05:00.560
Now, because we've updated an entity and this is going to be the case, whether you make a small change

05:00.560 --> 05:06.040
to the name of a property in here, or you create a new entity, or you update an entity, you always

05:06.040 --> 05:11.830
need to add a migration afterwards because we need this to be updated in our database schema.

05:11.830 --> 05:15.280
So I'm going to open up the terminal and I'm going to stop the API from running.

05:15.280 --> 05:19.720
Please do this because we do need to do this when we add a new migration.

05:19.720 --> 05:24.070
And I'm going to say dotnet EF migrations add.

05:24.070 --> 05:27.460
And I'm just going to say address added and press return.

05:27.460 --> 05:31.930
And this should go ahead and create our new migration.

05:31.930 --> 05:33.370
And great it's done.

05:33.370 --> 05:39.310
We also want to check the migration just to make sure things haven't failed silently.

05:39.310 --> 05:43.450
And we just want to make sure we got what we expect in this migration.

05:43.450 --> 05:48.340
So we're adding a couple of columns or we're adding a column to our users table.

05:48.460 --> 05:52.960
And then we're creating a table fully address and not much else to look at here.

05:52.960 --> 05:54.310
It's pretty straightforward.

05:54.310 --> 05:56.890
So I'm going to say that's okay.

05:56.920 --> 05:59.680
And then we'll go back to our account controller.

05:59.680 --> 06:03.370
And inside here we're just going to have a couple of endpoints.

06:03.370 --> 06:06.310
And these are going to be authorized endpoints.

06:06.310 --> 06:12.590
So I'll specify an http post and give it a route parameter of address.

06:12.620 --> 06:16.310
And say public async task.

06:16.850 --> 06:20.360
That's going to be an action result.

06:20.690 --> 06:24.410
And it's going to return a type of address.

06:24.710 --> 06:28.820
And we'll specify create or update address.

06:28.820 --> 06:30.680
We'll use the same method for both.

06:30.680 --> 06:34.790
And we're going to pass in the address and the address.

06:34.820 --> 06:40.100
And because this is going to be a related property to our user we can just use our user objects.

06:40.940 --> 06:44.060
The address property in our user object to set the address.

06:44.060 --> 06:49.310
So first of all we'll get hold of our user and we'll say var user equals await.

06:49.310 --> 06:55.070
And we'll use the sign in manager and the user manager dot users.

06:55.910 --> 07:05.150
And we will include because we need to include the address and say x goes to x dot address.

07:05.150 --> 07:17.230
And then we'll use first or default Async and we'll say x at the arrow and x dot username is equal to

07:17.260 --> 07:24.130
our user dot identity dot name.

07:24.130 --> 07:28.060
And make this or give it the optional parameter.

07:29.290 --> 07:30.700
And can I use that there.

07:30.730 --> 07:34.270
It doesn't appear so maybe I need to use it here first.

07:34.300 --> 07:36.520
No it's not letting me use this.

07:36.520 --> 07:40.420
And for short term purposes we can override this with an exclamation mark.

07:40.420 --> 07:45.760
We'll do something a bit better a bit later, but for the time being, just to save a bit of time,

07:45.760 --> 07:50.410
I'll use the shortcut cheat approach later just to override our compiler.

07:50.440 --> 07:55.450
We'll come back and make something a bit more reusable for getting our username.

07:55.480 --> 07:59.770
A bit later, and below our user, we'll check to make sure we have the user.

07:59.770 --> 08:06.100
So we'll say if the user is equal to null, then we'll just return unauthorized from this method.

08:06.160 --> 08:12.500
And speaking of authorized, let's also add the authorize attribute for this one, because of course

08:12.500 --> 08:15.620
we don't want anonymous users creating addresses.

08:15.620 --> 08:21.740
And that would give us a big problem in this line anyway, because if they're an anonymous user, then

08:21.740 --> 08:26.960
they certainly won't have a user claims principle for us to interrogate.

08:27.140 --> 08:34.400
And below the check, we will set our user dot address equal to the address.

08:35.660 --> 08:38.630
And then we can go ahead and save our changes.

08:38.630 --> 08:44.750
So or update our user I should say because that's what we're doing on this occasion.

08:44.750 --> 08:53.210
So we'll say var result equals await and sign in manager and user manager and update async.

08:53.210 --> 08:55.220
And we'll pass in the user.

08:55.640 --> 08:59.150
And then we can check to see if the result dot succeeded.

08:59.570 --> 09:02.720
And we'll use the not operator in front of that.

09:02.720 --> 09:12.490
And if it didn't succeed we're going to return a bad request and just say problem Updating user address.

09:13.900 --> 09:15.550
And then we can return.

09:15.580 --> 09:16.420
Okay.

09:16.420 --> 09:20.110
And we will return from this method the user address.

09:20.110 --> 09:21.730
And that should be fine.

09:21.730 --> 09:24.190
And below this one will create another endpoint.

09:24.220 --> 09:26.200
Again it's going to be authorized.

09:26.380 --> 09:37.120
And we'll give it a root of square brackets HTTP gets and specify address as the root parameter.

09:37.120 --> 09:47.620
And then use public async task that returns an action result of type address.

09:48.760 --> 09:54.760
And we'll use get saved address as the method name for this.

09:55.420 --> 09:59.920
So inside here we will specify var address equals await.

09:59.920 --> 10:03.790
And once again we'll use the sign in manager and the user manager.

10:03.790 --> 10:06.520
And then this gives us access to the users table.

10:06.610 --> 10:08.620
And we'll specify where.

10:08.680 --> 10:16.880
And we'll use x at the arrow and x dot username is equal to the user dot identity dot name.

10:16.880 --> 10:19.460
And I'll use the exclamation mark here.

10:19.460 --> 10:24.350
Again just to cheat a little bit, just for the short term, until we have a better way of doing this.

10:24.440 --> 10:31.850
Then I'm going to select and say x arrow x dot address, because that's what we want to select from

10:31.850 --> 10:32.600
our database.

10:32.600 --> 10:35.780
And then we can use first or default async.

10:35.870 --> 10:38.690
And we'll check to see if we have the address.

10:38.690 --> 10:49.490
So if address is equal to null then we will return no content not a not found in this case because a

10:49.490 --> 10:51.440
user doesn't have to have an address.

10:51.440 --> 10:56.150
But when we come to the checkout, we will check to see if the user does have an address, but if they

10:56.150 --> 10:56.450
don't.

10:56.480 --> 10:59.390
Not a problem, but we're just going to return no content.

10:59.390 --> 11:04.580
And if we do have the address we will of course return it.

11:05.180 --> 11:05.750
Okay.

11:05.750 --> 11:06.740
So that should be that.

11:06.740 --> 11:14.080
Let's go back to our terminal and use dotnet watch and make sure our app starts cleanly and deploys

11:14.080 --> 11:17.890
the new migration, etc. and that looks fine.

11:18.850 --> 11:21.160
And let's go check in postman.

11:21.190 --> 11:25.240
So inside postman we have a couple of methods here.

11:25.240 --> 11:27.850
We've got one to update the address and one to get the address.

11:27.850 --> 11:34.120
Let's just log in as Bob I'm going to use a login cookie and just say that Bob is the user that has

11:34.120 --> 11:35.980
the address we're going to be using.

11:35.980 --> 11:38.260
So I'm going to log in as Bob at test.com.

11:38.260 --> 11:41.590
Click send, make sure I've got the cookie and that's at 200 okay.

11:41.620 --> 11:45.160
Suggests that is the case if I try and get the address.

11:45.160 --> 11:47.440
At the moment there is no address for Bob.

11:47.440 --> 11:49.420
I would expect to see a 204.

11:49.420 --> 11:50.230
No content.

11:50.260 --> 11:51.250
Great.

11:51.250 --> 11:57.550
And if we use the update address and check the body, then what we have here is the type of address

11:57.550 --> 11:58.780
that we can send up.

11:58.780 --> 12:04.120
So I've got the name property line one a city a state postal code.

12:04.150 --> 12:05.320
That's not correct.

12:05.320 --> 12:09.160
That needs to be postal underscore code for this to work.

12:09.490 --> 12:12.070
And the country is GB.

12:12.230 --> 12:14.120
Stripe uses country codes.

12:14.120 --> 12:22.070
So using this when it does come to use the address later, this one will work.

12:22.070 --> 12:33.710
So each country has a two digit code USA would be US, UK is GB and I'm not a country code encyclopedia,

12:33.710 --> 12:39.650
so I don't know all the other ones, but well if you use this address it will work fine when it comes

12:39.650 --> 12:41.090
to testing this.

12:41.090 --> 12:47.150
And once we've got an easy way to enter an address in stripe, which we will do later, then it will

12:47.180 --> 12:49.010
be formatted in the correct format.

12:49.010 --> 12:50.960
So let's send this request.

12:50.960 --> 12:56.120
And this should update our database with that new address.

12:56.120 --> 12:57.830
And we can see that worked just fine.

12:57.830 --> 13:04.790
And then if I go and get the address and click send again, then what we should have is the address

13:04.790 --> 13:08.090
coming back from the API for that user.

13:08.090 --> 13:09.020
Perfect.

13:09.020 --> 13:12.050
So that's the API side of things dealt with.

13:12.080 --> 13:14.390
Next we'll take a look at the client side.
