Okay.
Another endpoint that we're going to add is we're just going to deal with the updating of address and
getting an address of a user, as when a user checks out, we want to see if or allow them to save the
address they want to use for shipping, and also retrieve that address when they enter the checkout
if they have a saved address.
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
done whilst we're dealing with identity related stuff.
Although this is just a normal thing that we're going to save into our database.
So we're going to create an entity for the address and I'll say new file select class and just call
this address.
And inside here we'll give this its necessary properties.
We'll have a prop that's an int that's an ID we'll have prop that's a string for the name.
We'll have a prop that's a string.
And we'll say line one.
And what we're going to do here really is match the properties that we're going to use in our payment
provider, which is stripe And these are the address properties.
There's many different ways of formatting address fields, but we're going to go for the ones that are
used by stripe and match them exactly.
So we're also going to have a string for line two as well.
And we'll have a prop that's a string for the city, and we'll have a prop that says string for the
state.
And we'll also have a prop that's a string for the postal code, and a prop that's a string for the
country.
And let's see what we need as required and optional properties.
So the name is going to be required for someone's shipping address.
So we'll put the name in as required.
Line one is also required.
Line two we're going to make optional as that is how it is in stripe.
They don't have to supply line two of their address and not every address has a second line.
The city will be required.
So I'll just copy this.
I'll ignore whatever warning that is for whatever button I accidentally clicked that caused that error
or warning, and I'll just put in required for the rest of these.
Another thing that I'm going to do that's slightly different to what we've done before.
Once I've got required in here, is we're also going to treat the postal code differently, because
the way that stripe returns this information is different to how we store it in C sharp.
And it's different enough because it uses an underscore in between the two words here for postal code.
We're going to use a slightly different approach for this one.
And we're going to use an attribute called JSON property name.
And in parentheses and quotes we're going to specify all in lowercase postal underscore code.
The idea being is that when we return an address and the JSON serializer formats our address into JSON.
Then it's going to use this as the property name.
Also, when we update an address, it's going to look for this property that has this formatting for
the property name.
And it will bind to this even though it doesn't match the name I've specified here, which is in C-sharp
conventional format.
Another thing we'll do that we haven't looked at before is I don't really want to send back the ID of
the address.
I need the ID in the database, so fine.
But I don't want to send this property back as part of our JSON response.
So another thing we can do inside here is we can use JSON ignore.
And when we do ask for an address we're going to get all of these properties.
But we're not going to get the ID we just don't need it.
And our address is going to be related to our user.
So we're going to have a 1 to 1 relationship between a user and an address.
We're not going to allow the user to solve multiple addresses.
Obviously you do see that kind of thing in many e-commerce apps, and you could go that far if you wanted.
It's not a big deal.
But for this example, on this training course, I'm just going to have a 1 to 1 relationship between
a user and the address, and I'll open up the user dot CSS.
And inside here we're going to effectively extend our user.
And we're going to use public int and have address ID and prop address.
And we'll specify address as the name of that property.
Now for both of these I'm going to make them optional because it's not going to be a requirement for
a user when they sign up or when they use our app to ever save an address, they can always just enter
the address manually in our checkout.
We won't force them to save an address, but they can do if they want to for convenience when they come
back the next time.
Now, because we've updated an entity and this is going to be the case, whether you make a small change
to the name of a property in here, or you create a new entity, or you update an entity, you always
need to add a migration afterwards because we need this to be updated in our database schema.
So I'm going to open up the terminal and I'm going to stop the API from running.
Please do this because we do need to do this when we add a new migration.
And I'm going to say dotnet EF migrations add.
And I'm just going to say address added and press return.
And this should go ahead and create our new migration.
And great it's done.
We also want to check the migration just to make sure things haven't failed silently.
And we just want to make sure we got what we expect in this migration.
So we're adding a couple of columns or we're adding a column to our users table.
And then we're creating a table fully address and not much else to look at here.
It's pretty straightforward.
So I'm going to say that's okay.
And then we'll go back to our account controller.
And inside here we're just going to have a couple of endpoints.
And these are going to be authorized endpoints.
So I'll specify an http post and give it a route parameter of address.
And say public async task.
That's going to be an action result.
And it's going to return a type of address.
And we'll specify create or update address.
We'll use the same method for both.
And we're going to pass in the address and the address.
And because this is going to be a related property to our user we can just use our user objects.
The address property in our user object to set the address.
So first of all we'll get hold of our user and we'll say var user equals await.
And we'll use the sign in manager and the user manager dot users.
And we will include because we need to include the address and say x goes to x dot address.
And then we'll use first or default Async and we'll say x at the arrow and x dot username is equal to
our user dot identity dot name.
And make this or give it the optional parameter.
And can I use that there.
It doesn't appear so maybe I need to use it here first.
No it's not letting me use this.
And for short term purposes we can override this with an exclamation mark.
We'll do something a bit better a bit later, but for the time being, just to save a bit of time,
I'll use the shortcut cheat approach later just to override our compiler.
We'll come back and make something a bit more reusable for getting our username.
A bit later, and below our user, we'll check to make sure we have the user.
So we'll say if the user is equal to null, then we'll just return unauthorized from this method.
And speaking of authorized, let's also add the authorize attribute for this one, because of course
we don't want anonymous users creating addresses.
And that would give us a big problem in this line anyway, because if they're an anonymous user, then
they certainly won't have a user claims principle for us to interrogate.
And below the check, we will set our user dot address equal to the address.
And then we can go ahead and save our changes.
So or update our user I should say because that's what we're doing on this occasion.
So we'll say var result equals await and sign in manager and user manager and update async.
And we'll pass in the user.
And then we can check to see if the result dot succeeded.
And we'll use the not operator in front of that.
And if it didn't succeed we're going to return a bad request and just say problem Updating user address.
And then we can return.
Okay.
And we will return from this method the user address.
And that should be fine.
And below this one will create another endpoint.
Again it's going to be authorized.
And we'll give it a root of square brackets HTTP gets and specify address as the root parameter.
And then use public async task that returns an action result of type address.
And we'll use get saved address as the method name for this.
So inside here we will specify var address equals await.
And once again we'll use the sign in manager and the user manager.
And then this gives us access to the users table.
And we'll specify where.
And we'll use x at the arrow and x dot username is equal to the user dot identity dot name.
And I'll use the exclamation mark here.
Again just to cheat a little bit, just for the short term, until we have a better way of doing this.
Then I'm going to select and say x arrow x dot address, because that's what we want to select from
our database.
And then we can use first or default async.
And we'll check to see if we have the address.
So if address is equal to null then we will return no content not a not found in this case because a
user doesn't have to have an address.
But when we come to the checkout, we will check to see if the user does have an address, but if they
don't.
Not a problem, but we're just going to return no content.
And if we do have the address we will of course return it.
Okay.
So that should be that.
Let's go back to our terminal and use dotnet watch and make sure our app starts cleanly and deploys
the new migration, etc. and that looks fine.
And let's go check in postman.
So inside postman we have a couple of methods here.
We've got one to update the address and one to get the address.
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
the address we're going to be using.
So I'm going to log in as Bob at test.com.
Click send, make sure I've got the cookie and that's at 200 okay.
Suggests that is the case if I try and get the address.
At the moment there is no address for Bob.
I would expect to see a 204.
No content.
Great.
And if we use the update address and check the body, then what we have here is the type of address
that we can send up.
So I've got the name property line one a city a state postal code.
That's not correct.
That needs to be postal underscore code for this to work.
And the country is GB.
Stripe uses country codes.
So using this when it does come to use the address later, this one will work.
So each country has a two digit code USA would be US, UK is GB and I'm not a country code encyclopedia,
so I don't know all the other ones, but well if you use this address it will work fine when it comes
to testing this.
And once we've got an easy way to enter an address in stripe, which we will do later, then it will
be formatted in the correct format.
So let's send this request.
And this should update our database with that new address.
And we can see that worked just fine.
And then if I go and get the address and click send again, then what we should have is the address
coming back from the API for that user.
Perfect.
So that's the API side of things dealt with.
Next we'll take a look at the client side.