4.5 Implementing a Web API
Browsers aren't the only clients we need to serve. We should also provide a web API for other programs or web services that want to access our raw message data. In this lesson, I'll show you how to add an API in just a few minutes!
1.Introduction1 lesson, 01:12
2.Getting Started2 lessons, 22:54
3.Request Handling5 lessons, 1:06:56
4.Displaying Data5 lessons, 1:15:23
5.Conclusion1 lesson, 00:39
4.5 Implementing a Web API
Adding a web API to an MVZ6 application is very easy to do. Because after all, MVZ6 is a unified API. So everything that we have talked about, as far as controllers are concerned, apply to Web API as well, because it doesn't matter what type of controller it is. If it's a MVC controller, which I'll call a Web UI controller, or a Web API controller, they all inherit from Controller. So this means that we can take our existing message controller, and we can add some web API features to it. One of the things that we could do is, inside of our existing action methods, is do something called content negotiation. Where we determine what type of format the client is requesting, and we do that with the accept header. So we could check the accept header and if the client is wanting JSON, then we can simply return JSON. We can pass in our model, which would be our list of messages in this case, and it would serialize our messages as a JSON structure. And return that. That's how I was originally going to cover Web API in this lesson, but instead I decided that if I were writing a Web API for an existing controller I would want to have a different URL. So for example, I would want the browser to go to messages, and then that would display our index. But in order for another client to retrieve the JSON structured data, I would want them to go to like API/messages. For one, that makes our action methods more concise. We have less complex stuff going inside of them so therefore they are easier to maintain and understand what's going on, and plus it separates them. If we ever need to make changes to our web API, an only our web API, then we could do that inside of the action methods responsible strictly for For providing the web API. So we are going to write three action methods, one for retrieving all of our messages, one for retrieving the messages by user, then of course one for retrieving an individual message. So it's going to look very similar to what we have. But instead of returning a view it's simply going to return the data that we want to retrieve. So let's start with the action method that will retrieve all of our messages. We first of all want to allow anonymous and and then we also want to define the route. Now let's first of all talk about the URL that we want our API to have. Usually you have /API and then you get into whatever it is that you are retrieving. In this case, it would be messages. And that would be the URL for retrieving all of our messages. Now, the problem here is that, because we have defined messages at the controller level, messages is going to be the first segment of our url, and we don't want that. We want API to be the first segment. So it would look like this: http://localhost/api, and so on and so forth instead of /messages. Well we can do this very easily. We can just begin our URL here with a tilde and this is going to tell the routing engine that this URL is going to begin with API as the first segment. So now we can just write our action method as normal. Public asynch task. And instead of returning an I action result which result, which we could do if we wanted to. We could just return an IE numerable of message view model. And behind the scenes NVC is going to automatically serialize our data as JSON. Everything is JSON by default. So let's call this method GetMessagesAsync, and we don't need any parameters. Now we want to retrieve our messages, so we can come up here to the index action method. We can copy that line of code and paste it in, and then we can simply return messages, and that's all that we need to do. It's very very simple. So we can take this method, copy it, and then let's paste it after the display by user and we want to change this method to GetMessagesByUser, so that that is descriptive as to what this is doing. And then we just want to essentially copy what we did in the display by user. So first of all, GetMessagesByUserAsync, and we need to change our route here. We want the user name, so we're going to add a route parameter called username. And then we need a parameter to the method itself, so string username. And then, we want to retrieve the messages by the username, and then pass that on. Now, we should also do what we did in the display by user action method. If the messages are null, that means that the user name doesn't exist. So in that case, we want to return an HttpNotFound. But we can't do that, can we? Because HttpNotFound is an action result and we are returning an actual type. So here's what we can do. We can change this to be a task of IActionResult, and instead of returning JSON and then passing in messages, we can return NewObjectResult And pass in messages. Now the reason why I'm going with object result here, is because that's essentially the same thing as returning the type, as to what we did before. So, and this is just gravy. We can return JSON. Explicitly if we wanted to. But this way it's a little more like what we were doing before, but now we have the benefit of returning in the action results so that we can use HTTPnotfound. And we could do that up here for the get messages asynch, but you know, this isn't going to be not found, we are always going to return something. It might be an empty array, but we will at least have something. So, going forward we will use this pattern. So let's copy this method, and after the display by ID method, let's paste that here. Let's change this to GetMessageByIdASync, we need to change the parameter from a string to an int and we also need to change the name. Because we are going to change the route parameter from user name to ID, Let's also add the constraint that this is an integer. And then we want to do essentially what we did in our other method. We want to retrieve the message. If it's null then return http not found. Otherwise, we will return a new object result and we will pass in our message. So, this is really it. I mean, as I said, it's very simple. It's much like what we have already done, except that now that this is explicitly for our API and it's going to return JSON. So, we can run this application. And let's first of all test the existing stuff that we had. So we want to go to /messages, and we want to ensure that we see our list of messages. We can see the individual message and we can also see the message by user. Now we can also test our web API with internet explorer, however it's going to want to download a JSON file. So instead, we are going to use Chrome, because as you can see, it displays stuff. So, let's go to api/messages, and here we have our three messages. We can see one user name, we see another user name, and then another user name. So, all three messages. If we want the messages by bar at bar.com then we will see just one message. And if we want to retrieve the single message of one, then we have that as well. Now, if we do something that doesn't exist, like let's do an ID of four. We should get a 404. Well we got something, it's just not what we expected. Oh well. We could fire up Fiddler and we could inspect all of these requests if we wanted to do that. And if you don't have Fiddler, or if you don't know what it is, it is an HTTP debugger. And it is definitely something that you should have in your toolbox. So, actually let's fire up Fiddler, and let's see if we are actually getting a 404. So, Fiddler and we want to use the composer here because this is what allows us to make a request, or we could just make the request again through Chrome and see what we get. Because Fiddler will log all of the http requests that are made, and it will show you the requests, all of the headers, all of the the data that was with that request, it will also show you the response. So we can just press enter again there and then we can go back to Fiddler and we can see that yes, we are getting a 404. That is our result. We can see that our request was to API/messages/4. And just to show you what Fiddler can do, we can also display our list of messages here and we can go to fiddler and over here in the right hand side, we can look at the request that we sent. We can see all the headers that were sent. And then we can look at the response. We can look at the headers, we can look at the actual text that came back. But since this is JSON ,we can use the Jason formatter and we can see all of our data, as formatted as JSON. So as you can see, adding Web API features to an NVC 6 application is very easy to do because it's all the same API. You don't have to relearn anything. You can apply the same concepts that you learned with the Web UI to the Web API.