WEBVTT

00:00.000 --> 00:00.270
Okay.

00:00.270 --> 00:08.520
Our next task is to create a web API controller that's going to be responsible for receiving HTTP requests,

00:08.940 --> 00:15.480
querying our database, and then returning the results in an HTTP response so that we can test this

00:15.480 --> 00:17.400
using our browser.

00:17.580 --> 00:25.380
So let's clean things up at the top and inside Solution Explorer inside the controllers folder.

00:25.380 --> 00:27.810
Let's go ahead and create a new file.

00:27.810 --> 00:30.750
And we do have a template for an API controller.

00:30.750 --> 00:33.660
So let's use this to see what it gives us.

00:33.660 --> 00:38.850
And we're going to call this products controller and press return.

00:38.850 --> 00:43.290
And this gives us the boilerplate for a typical API controller.

00:43.410 --> 00:49.350
And if we compare with an existing controller we have the demo one that was provided, the weather forecast

00:49.350 --> 00:49.800
controller.

00:49.800 --> 00:57.810
We can see that the start of the class resembles what we've just created via the template.

00:57.810 --> 01:00.430
We've got effectively a roots.

01:00.430 --> 01:07.960
How does Net know where to send the HTTP request that's coming in to the correct API controller?

01:08.350 --> 01:10.540
Well, it uses the routing system.

01:10.540 --> 01:18.490
So in order to access this controller we would need to use in our case https colon forward slash forward

01:18.490 --> 01:23.050
slash localhost colon 5001 forward slash API.

01:23.290 --> 01:25.030
And then this controller part.

01:25.060 --> 01:30.220
This is a placeholder for the name of the controller minus the word controller.

01:30.610 --> 01:36.670
So by convention this is if our API controller is called products controller.

01:36.670 --> 01:43.090
Then to access the endpoints in this controller we would use API forward slash products.

01:43.750 --> 01:46.720
Now this next attribute and these are known as attributes.

01:46.750 --> 01:50.530
These things in square brackets is API controller.

01:50.530 --> 01:57.190
And if we hover over this then this indicates that a type in all derived types are used to serve http,

01:57.220 --> 02:04.420
API responses and controllers decorated with this attribute are configured with features and behavior

02:04.450 --> 02:08.140
targeted at improving the developer experience.

02:08.140 --> 02:11.380
That's us for building APIs.

02:11.380 --> 02:12.790
So great.

02:12.790 --> 02:13.840
That's useful.

02:13.840 --> 02:19.870
And we won't talk about this now, but we'll take a look at some of its features a bit later on as we

02:19.870 --> 02:26.380
use some of its features, but it's not going to affect what we do in this controller at the moment.

02:26.380 --> 02:28.090
We'll just leave it in place.

02:28.360 --> 02:38.440
Now inside our API controllers, we create API endpoints and HTTP requests, use HTTP methods, things

02:38.440 --> 02:41.110
like an http get an http post.

02:41.110 --> 02:47.170
If we were going to create a resource, a get would be for a query for a resource, a put would be if

02:47.200 --> 02:49.810
we're updating a resource and delete.

02:49.840 --> 02:55.030
No prizes for guessing what that does, but it would delete a resource of course.

02:55.030 --> 03:01.190
So this one we're going to use the http get attribute, because we're going to get a list of our products

03:01.190 --> 03:02.480
from the database.

03:02.780 --> 03:09.410
Now we return a HTTP response from these HTTP endpoints.

03:09.410 --> 03:14.540
And the way that we do that in dotnet is we return an action result type.

03:14.540 --> 03:21.830
And we can specify what type of thing we're going to return in this result using the angle brackets.

03:21.830 --> 03:25.640
And we're going to return a list of products.

03:25.640 --> 03:30.590
And we need to bring in the using statement for where product has been defined.

03:30.620 --> 03:33.920
So we can where we've got the arrow, we can use our quick fix.

03:34.070 --> 03:38.510
And we can specify we want to use using API entities.

03:38.630 --> 03:41.270
And that gets added at the top here.

03:41.270 --> 03:44.600
So then we'll give the method a name.

03:44.600 --> 03:47.090
And we're going to call it Get products.

03:47.090 --> 03:51.980
And inside here we are going to return.

03:51.980 --> 03:58.600
And at this point we do need to inject our store context and the way that we inject.

03:58.600 --> 04:03.670
I'm just going to demonstrate two ways very quickly about how we inject something into our classes.

04:03.670 --> 04:11.230
There's the old fashioned way where we'd create a constructor using the snippet like so, and then we'd

04:11.230 --> 04:13.270
specify the thing that we want to inject.

04:13.270 --> 04:16.150
In this case, it's the store context, and we give it a name.

04:16.660 --> 04:24.250
And then what we would also do is we'd put our cursor inside context, and then we would use the create

04:24.250 --> 04:26.290
and assign field context.

04:26.290 --> 04:32.230
And this would create a private read only field that we can then access inside our method.

04:32.230 --> 04:33.550
Here I can say context.

04:33.550 --> 04:37.240
And this gives us access to Entity Framework queries.

04:37.240 --> 04:44.710
And it also populates the constructor and assigns the read only field context to list context which

04:44.710 --> 04:46.930
refers to list context.

04:46.930 --> 04:48.700
I'm highlighting here.

04:48.700 --> 04:52.870
So this context is effectively this.

04:52.870 --> 04:59.060
And then we're setting This context using this equals here.

04:59.060 --> 05:00.680
But there is a better way to do this.

05:00.680 --> 05:02.720
And we've got our ellipses here.

05:02.720 --> 05:06.680
So let's use the quick fix and we'll use the primary constructor.

05:07.280 --> 05:09.440
And then we've got access to our context.

05:09.440 --> 05:13.280
And there's no point in this read only line now so we can remove that.

05:13.280 --> 05:15.950
And now this gives us access to our context.

05:15.950 --> 05:18.470
And this is dependency injection.

05:19.100 --> 05:25.160
And when a new instance of our products controller is created which happens when it receives an HTTP

05:25.160 --> 05:30.050
request, then it instantiates a new instance of the store context.

05:30.080 --> 05:33.650
If we didn't define this as a service, then this would not work.

05:34.130 --> 05:37.880
But we have defined this as a service, so this should work.

05:37.910 --> 05:45.050
And then inside our Getproducts method we can return the context and products.

05:45.050 --> 05:47.870
And we can say to list.

05:47.870 --> 05:52.640
And this two list method is going to query our database.

05:52.640 --> 05:57.070
So all of the products in the database, we're going to output them to a list, and that's what we're

05:57.070 --> 05:59.110
going to return from this method.

05:59.200 --> 06:03.490
Let's create another method that will allow us to query for an individual product.

06:03.490 --> 06:05.470
So we're going to say Httpget.

06:05.710 --> 06:08.620
Then we'll add parentheses then quotes.

06:08.620 --> 06:16.150
And then in curly brackets we specify id and this is the ID of the product that we want to fetch from

06:16.150 --> 06:16.870
the database.

06:16.870 --> 06:18.280
And we'll use public.

06:18.400 --> 06:20.890
Again we'll use Actionresults.

06:20.890 --> 06:26.650
And this time we're just going to return a single product and we'll call it get product.

06:27.100 --> 06:31.780
And we need to specify the ID that we're receiving as a route parameter.

06:31.780 --> 06:39.370
So for list method it's going to be API forward slash products forward slash let's say two for instance.

06:39.370 --> 06:45.850
And this integer, the ID that we're passing in as a route parameter that's available here.

06:45.850 --> 06:49.450
We can pass as an argument to our get product method.

06:49.480 --> 06:53.640
Then inside here we can query our database.

06:53.640 --> 06:57.630
So I'm going to say var product equals context dot products.

06:57.630 --> 06:59.430
And then we've got a find method.

06:59.430 --> 07:02.670
And we can find a product that matches that ID.

07:03.510 --> 07:08.610
Now if we hover over the product at this point it will tell us what we're getting from our database

07:08.610 --> 07:10.620
and where we see that question mark.

07:10.620 --> 07:15.930
That means it could be a product, or it could be null, because our compiler doesn't know whether or

07:15.930 --> 07:18.330
not the product exists in our database.

07:18.330 --> 07:24.240
That matches the ID, because it also doesn't know what the ID that we're trying to look for at this

07:24.240 --> 07:25.020
point is.

07:25.020 --> 07:28.980
So it doesn't know if we're actually going to get a product back from the database.

07:28.980 --> 07:35.790
But if we take a look at the find method, then it finds an entity with the given primary key values

07:35.790 --> 07:37.950
and so on and so forth.

07:37.950 --> 07:41.280
But if no entity is found, then null is returned.

07:41.280 --> 07:43.680
So this could be a product or it could be null.

07:43.680 --> 07:46.860
And we need to check to see if that is indeed null.

07:46.860 --> 07:50.910
So we're going to check to see if the product is equal to null.

07:50.910 --> 07:53.120
And if it is we're going to return.

07:53.150 --> 08:00.260
And because we're in the context of an HTTP controller, we can return a not found which will result

08:00.260 --> 08:03.860
in a 404 not found being returned to the client.

08:03.890 --> 08:08.660
Then we can return the product, because at that point we know we have it.

08:08.690 --> 08:14.120
If we do comment out this line actually where we're returning not found, then we do get a warning to

08:14.150 --> 08:16.040
say, hey, product could be null here.

08:16.040 --> 08:23.060
So you do want to check for this, but if we put this line back in then the warning will go away.

08:23.630 --> 08:25.160
So that's our API controller.

08:25.160 --> 08:29.930
And if we go and test this in our browser right now, and let's go back to the tab with the weather

08:29.930 --> 08:30.530
forecast.

08:30.530 --> 08:35.960
And I swap weather forecast for API products and press return.

08:35.960 --> 08:37.670
Then I get an exception at the moment.

08:37.670 --> 08:44.930
And the reason for this, and this is very consistent, is that in when we add a new API controller,

08:44.930 --> 08:50.510
we always need to restart our API server before this is registered with our application.

08:50.540 --> 08:52.000
So let's go back to the terminal.

08:52.210 --> 08:55.300
And if I just scroll down, there's a couple of ways to do this.

08:55.330 --> 09:01.240
We can either use control and R, or we can use control C to stop our application.

09:01.240 --> 09:04.870
And then just use dotnet watch to restart it.

09:05.140 --> 09:08.530
And it does say there we can use control R to restart as well.

09:08.530 --> 09:11.260
So either approach will fix this.

09:11.260 --> 09:17.560
And if we go back to the browser and let's just make that request again, this time we can see that

09:17.560 --> 09:21.190
we're getting a list of products back from our database.

09:21.400 --> 09:27.610
And if I try and get an individual product, let's say product with the ID of three, then we get the

09:27.610 --> 09:32.140
product that matches that particular ID back from our database.

09:32.710 --> 09:33.640
Great.

09:33.640 --> 09:37.510
But we're not going to be using our browser to test our API functionality.

09:37.510 --> 09:42.730
It's fine just for a few get requests very quickly and easy to test, but there's a better tool that

09:42.730 --> 09:45.700
we're going to take a look at to make these API requests.

09:45.700 --> 09:48.370
And I want to introduce that in the next lesson.

09:48.370 --> 09:50.500
And we'll take a look at postman.
