4.3 Writing the Views
We now have everything we need to display messages... except the views themselves! In this lesson, we'll write our views. I'll also show you how to use a partial view to reuse markup.
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.3 Writing the Views
In the previous lesson, we started writing the code necessary for displaying different views of our messages. In fact, we are pretty much done, except that we need to write the actual views. So there's no bonus points as to guessing what we are going to do in this lesson. Now, as a quick little recap, we have three methods for displaying messages. We have the Index method for displaying all of our messages. Then we have the DisplayByUser, which is going to display all of the messages written by a particular user. And then we have the DisplayByID method, to display an individual message. Now the Index and DisplayByUser are almost identical. And in fact, the only difference is the data that we are passing to the view. So it doesn't really take a leap to think that we can use the same view for both of these methods. In fact, this is very common. If we find that we need to display very similar information, then we can reuse the same view. So, really with a few minor tweaks we can take the Index view, and use that as the view for Index and DisplayByUser. However, the first thing I want to do is actually change the name, because it is no longer really just the Index view, this is for displaying a list of messages, so we can say DisplayLists. And I'm sure we can come up with a better name, but that is going to be sufficient for our needs. So we can go back to our controller. And now we need to be explicit as to what view that we are going to use. Because we changed the name of the view, It's no longer Index. So all we have to do is pass the name of the view that we want to use as the first argument to our view method. So we pass in the string, DisplayList and of course, the casing does not matter because this is a Windows system. And we'll just use the same view for the DisplayByUser. Now it would also be nice to have a little heading. So that's if it's the Index then we can say, these are all the messages, and if it is displaying by a user, then we can say messages by, and then the username. So let's add, let's say an H2 element. And this is where we could use our ViewBag. Now we don't want to use the ViewBag too often. But in a case like this, it really makes sense to do so because while this could be considered view model data, going through the motions of creating a new model class and everything, just really doesn't give us any benefits. If we can use the ViewBag here to just set the value that we want inside of this heading, then we've gained a lot of time and it's really easy to do. So let's say that the ViewBag is going to have a property called Heading and inside of our action methods we are going to set this value. So we go back to our controller and for the Index action we can set ViewBag.Heading = and we can just say All Messages. And then for the DisplayByUser method we can say Messages by, and then we can say the username. Whatever was supplied as the username parameter. So Messages by, and then we will simply concatenate, username. Now inside of the DisplayByUser, we do need to check to see if messages is null, because if messages is null, then the username that was applied doesn't exist. So let's go ahead and add that check. Messages == null, and then we will simply return HttpNotFound. And we could also add another check to see if we have any elements within this messages collection. And if we don't, then we could display another view that says, there are no messages. But for the sake of simplicity, we're just going to leave this as is. So if we run this, let's do Ctrl+F5, we will want to go to messages. And we should see our list of messages, and we should see that heading. So let's just go to messages. This will also give us a chance to test the things that we did in the previous lesson. So remember that we changed the URL to messages instead of message, and you can see that we have our list of messages, and we also have the heading of All Messages. And it would be nice if we had links for the usernames, so that we could click on one of these links, and then that would take us to the page that would display the messages for that user. So let's go back to our view and let's make some modifications here. We want to add a link, and we can generate a link in one of three ways. We can of course just hard code our anchor element and its href attribute. That's always an option. But there is a down side to that. We can rely upon either the HTML helper, or the tag helpers to generate our anchor element. And the reason why you might want to use these, is because if we ever change our URLs, or if we change our routing, then we don't have to go back and modify our links. If we hard coded our anchor elements with their href attributes, then we would have to come back and make the necessary changes, and that's okay, but it can also be a headache. If we rely upon On the HTML helper. It has an action link method. It also has a route link method. And if we supply the appropriate information, then it's just going to generate the correct anchor element. The same is true for our tag helper. And that's what we're going to use here. Now, we need three pieces of information. We need the action name. We need the controller. Then we also need the username, because that is part of our route here. The routing engine is going to take the username from the request, and pass that on to the DisplayByUser method. So, we need to first of all specify the action. And we do that with asp action, and this is DisplayByUser. Now, casing doesn't matter, but I'm going to use Pascal casing, because it's a little easier to read here. So we have DisplayByUser. We also need to specify the controller, and that is going to be Message. Now it's not Messages. Messages is part of the URL. But the controller name is Message controller. So be sure that that is singular. And then we need to supply the user name value. We do this with asp routes. And we use that as a prefix. And then we use whatever value that we need. So in this case that's username. Because that is what we have as this route's parameter here, if you will. So we want to set asp-route-username="@message.Username". And then for the text of our anchor element, we want the username again, so @message and then Username. We need to get rid of this just plain text, Username. Now if we go back to the browser and refresh, then we are going to see our links. And if you look in the status, we have the appropriate URL. Now, you can see that the @ sign is URL encoded. But, that's not going to cause a problem, that's going to take us to the appropriate page and here we see all the messages by firstname.lastname@example.org. If we go back and go to email@example.com, then we see that message as well. But we could also use the @ inside of the URL. If we hard code that in then we see the same information. So, if somebody wanted to type that in they can, but our system is going to automatically encode the @. So we have the views for displaying all of our messages. We also have the view for displaying the messages by a given user. Now let's add the view for displaying an individual message. And we have already the HTML that we want. We want to grab this div element and really everything inside of it. So let's do that. Let's copy, let's go to our Message folder inside of Views, and let's add a new MVC View Page. And let's call this DisplaySingle. We have a display list so it makes sense to have a display single. And let's just paste that code in. Now let's also go back to the display list, and let's grab the @Model statement and the @Using, because we will need both of those. We do need to change the Model, however. it is no longer an IE numeral of MessageViewModel. We are simply accepting an object of type MessageViewModel. Now we need to change @Message to @Model, and that's really all that we are going to do here for now. We are going to come back and make a change, because if you notice, we have the same HTML used between the display single and display list. So we need to simplify that, so that we can use the same HTML between both, and we don't have it actually listed inside of these views. But first, let's go back to the message controller. And we need to specify what view that we want to use for the DisplayByID. So here we have the DisplaySingle. So we will pass that as the first parameter. And then we want to pass in our model, which is a message. Now here we also need to check if we have a message. If not, then we can return a 404. So if message == null, then return HttpNotFound. So we can also add a link for the title. So let's go to our display list. And instead of just displaying the title we can have a link, so that whenever we see our list, we can click on the title and that will take us to the individual message. So we can use the tag helper once again. Let's do asp-action. This is gonna be Display, well, what did we call that? Let's see, DisplayById. So DisplayByID. The controller is going to be the message controller. And then we also need to specify the ID, and we do that once again with asp-route-id=, then @Message.ID. For the text of this link we want to use the title, so let's just use that. And we should now have a link. Let's go back to the browser. Let's refresh here, and hopefully we will have the correct link. And if we look in the status, we do. We see messages and then one. So if we click on this we should see, the page for that individual message. We do. So let's go back, let's click on Second Message, and everything appears to be working. Now, if we go to /edit, that's something that we haven't tested yet. This should take us to the Log in page. Because remember that we have protected that resource, and we need to Log in. So that is for the bar user, so let's do firstname.lastname@example.org. And here we can edit, was edited, let's edit the message. We go back to the index, and we see Third Message was edited. So it looks like everything that we did in the previous lesson seems to be working. Now we just need to simplify the display list and display single views. Because we have what is essentially the same markup. So if we could put this markup into another file, and then reference that file inside of these two views, then, that would be ideal. That way we have just one place that we need to modify if we ever need to modify that mark up. And that's exactly what a partial view is. And I've briefly talked about partial views, but we've never really just looked at them, so, here we go. A partial view is exactly what it sounds like. It's part of a view. It's not directly used by an action method. So whenever we create our partial view, it's going to have the underscore as the first character in the name. Now let's do a search for partial and let's see if there are any templates, and there's not. But that's okay, because a partial view is a lot like a normal NVC view page. So we will use that template, and let's call it _ and then SingleMessagePartialView. That way we know that this is a partial view for displaying a single message. And of course it begins with an underscore. So we will add that. And then we want to specify the model. Because you can pass a model to a partial view. That's what makes a partial view, something that we would want to use. So let's go to our display single view, and let's copy the @using and the @model statements, so that we can past them inside of our partial view. And then let's grab the HTML from our display list. Now we just want from the div element, and really that's it. We just want the div element and everything in it. Now, the reason why I am choosing to use the HTML from display list, is because we have this link for our title. Now of course that's minor, but I didn't want to copy and paste multiple times. So we just need to change @Message to @Model, and you can see that it looks almost exactly like a normal view. It's just that it's going to be used from inside of another view. So we can go to our display single view. Let's get rid of this HTML. And we want to use @html, and then there is a partial method. We need to specify the name that we want to use, _SingleMessagePartialView. And then we pass in our model, which is the model that we passed to this view. And then we essentially want to do the same thing inside of the display list. So, we will get rid of this markup in here. And then we will paste in the call to Html.Partial. And for the model, we will pass in the message. So whenever we go back to the browser and refresh, we are going to see a link here. Now, our title changed, it used to be Third Message, I think it was, edited. And the reason why that's changed is because our code had to recompile. So our data store and I'm using air quotes around that, is in memory, and because we had to recompile, then everything that was in memory got dumped because our data store was recreated. So let's go back, we have our links here. So we can see that for our list of messages, we have exactly what we had before. If we look at the view for displaying messages by user, we have the same thing there. And if we look at the view for displaying an individual message, well, we have kind of what we had before, the only difference is that we now have a link for the title. Well there is one other thing I want to do. When a user is logged in, I want them to have easy access to the edit form for their messages. So instead of displaying the user link, for their messages, I want to display an edit link. So this is very easy to do. We just want to check to see if the currently logged in user, is the user that authored the message. So we will do that inside of our single message partial view. Let's first of all add a using statement to System.Security.Claims. If you'll remember, we added this name space inside of our message controller, because that gave us access to an extension method called GetUserID. That way we can retrieve that value rather easily, and we don't hit the database every time that we're going to use it either. So, It's really ideal here. We want to check to see if User.GetUserId == Model.UserId). And if so, then we want to display an edit link. Otherwise, we want to continue to display the user link. So, we will just add in an else statement and our existing link will be inside of that else statement. Now we can copy this link, and use that as a basis for our edit link. We, of course, need to change the action to Edit. The asp-controller is going to be Message. But we need to change the route. Instead of Username, we need to specify ID. And, of course, we need to use Model.Id. And that will give us the value that we need. Let's change this to Edit, actually, let's do Edit Message. And now, we can go back to the browser. Let's refresh this page, and we should see our links. We have the links for the users that is not currently logged in. So if we click on this, we of course go to the messages by email@example.com. Otherwise we see that we have this Edit link. And if we click on that, that takes us to our Edit page. So we can say that this was edited again, because this is the second time that we have edited it. And there we go. So now, our soundboard application is completely functional. There's just a couple more things that we need to do, and we will cover those in the next lessons.