4.4 Using a View Component
It would be nice to also display the titles of the latest messages on our front page. In this lesson, I'll show you how easy it is to add this functionality with a view component.
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.4 Using a View Component
In the previous lesson, we created a partial view responsible for displaying a single message, and then we used that partial view inside of larger views that were also responsible for displaying messages. So while I use the term component in order to describe a partial view, there usually is some type of relationship between the larger view and the partial view that it uses. Now, I'm making this distinction because there is another feature in MVC6 called a view component which is an actual component. It is something that we can use anywhere within our application and it's primarily used to display content that doesn't have any type of relationship around it. For example, let's run this application and let's look at the home page. Now of course what we see here is generated by Visual Studio. Whenever you create an MVC application, you use the default template, it's going to create a working application for you. But I want to focus on this content at the bottom. We have three columns. While this content here isn't actually generated by a view component, if we wanted to list, let's just say the latest five messages in our system as an unordered list so that it would look just like this. We could do that with a view component and then put that in one of these columns. The reason being because this is content and it's useful content, but it's not really related to the overall view. So let's do just that. Let's create a view component that is going to display the latest five messages. And of course it's going to be just the titles, and they will be linked so that we can click on those links and then go to the individual message. Now you're going to see several similarities between a view component and a controller. In fact, a lot of it follows the same MVC pattern. But you can think of a view component kind of as a mini controller. So the first thing we want to do is create a folder that's going to contain all of our view components. Now, we're just going to create one, but within a real application, we would probably have multiple view components. So we could create a folder to contain all of them. Now the name of the folder doesn't matter. But the name of the class that we are going to create does. Let's call this LatestMessagesViewComponent. Like a controller, a view component class needs to end with the term ViewComponent. Now there is an exception. You can omit ViewComponent, but you have to specify that this class is a view component by using an attribute. That attribute is called view component, and it resides within the Microsoft ASPnet MVC name space. Now here you can specify the name of the view component which in this case would be simply latest messages. And if you choose to use the attribute then you can name your class whatever it is that you want. So we can have a class of Foo if we wanted too. And as long as this view component attribute was there then the system would know that this is a view component. However, we are going to use just the normal convention of the class name ending with the term ViewComponent. And regardless of if you have ViewComponent in the name or if you're using the ViewComponent attribute you need to inherit from the ViewComponent class. So there is a similarity between a ViewComponent and a controller. Our controllers inherit from controller. Our view components from ViewComponent. And inside this class, we want to define a method called Invoke. It needs to return an IViewComponent result and we can accept any arguments that we want, in order to generate the content that we need to generate. So we are going to generate a list of messages. We could accept the maximum amount of those messages that we want to display. So if we ever decide to show more than five, then we can change that whenever we call the invoke method. So we want to display our messages. We need our message repository, so let's make this a private readonly field, and we want MessageRepository. We need to include the data namespace. Let's just call this _messages. Now we also want to do what we did in our controllers. We want this message repository given to us through our constructor, and we want to use the built-in dependency injection features of NVC6. So we will have a constructor that accepts a message repository. We'll just call it messages, and then inside of the constructor, we will set our _messages = messages. And now we have everything that we need. We just need to get our model, which is going to be our list of messages, and then pass those on to what is essentially going to be the view. So let's do var messages = and we want _messages. Now, we don't have a method specifically for retrieving the latest messages, so instead, we're just going to use the getAll method. And let's go ahead and order by descending, using the date as our sorting value. So that is the created date. And then we want to take whatever has been specified by our count parameter. And that will give us our model. So all we have to do is return and view. Passing in our messages. Now, in a real application, we would have an actual method for retrieving the latest messages. But for the sake of this lesson and this application, this code is going to work just fine. So now we just need to create our view. And we would normally do this inside of the views folder for wherever we are going to be using this view component. So because we would be showing this on the home page, which is inside of our home folder, This is where we would put the view for our view component. However, we can also put it inside of shared. And if we put it inside of shared, then we can use it anywhere. So that's what we are going to do because we never know where we would want to use this view component. So inside of the shared folder, we need to create another folder and this has to be called components. It can not be called anything else or MVC6 will not find this view. And in the inside of this components folder, we need to create another one that has the exact name of our view component. So in this case it is latest Messages. And then we can use whatever name that we want for our view. Now, the default is to simply call it default. And whenever the view method executes it's going to use that default view. However, we can also do what we did inside of a controller, and we could specify the view name if we wanted to. So, if we wanted to use a view called foo, then we would pass the view name, foo, as the first argument and then the model as the second. But in this case, we'll just stick with the default and let's add a new MVC view page, simply called default. And then this view is going to look a lot like our other views. At the very top we need to define our @ model statement. So lets do @model and this is going to be in IEnumberable of message. This is not our message view model. Now, we could use our message view model, but that would also mean that we would need to convert our messages into a message view model, and there's really no need to do that, because here, we are just displaying the titles, and all we need in order to display the titles is of course, the title and also the message ID. So we don't need any user information. And then we just need to output our unordered list. So we can start with our unordered list, and then inside of here, we can have our for each loop of our our message and model. And then we want our list items, so li_elements. And then we can use the tag helper syntax in order to generate these links. So we want to asp-action. That will be for displaying a single message. And I forget what that action is called, so let's jump over to our MessageController and let's find that action. There it is, DisplayById, so we want that value as asp-action. We need the asp-controller = message and then we also want to define the ASP route and then ID and we want that value to be our message ID, so at message.ID. And then for the text of this link, we want @message.MessageTitle, and that's it. Now we just need to invoke our view component and that will display our list of messages. So let's go to the _layout file. Let's see if this is where those three columns are. And I'm not seeing anything, so it's not in here. Now, I don't think we've really talked that much about a layout page. So let's just briefly go over it because Layout pages are really easy. So first of all we have all of this HTML, you can also see that there are some tag helpers being used to generate links here. Now we have this method called render body. This is where the body of a view is going to be put. So if we open up, let's say, the create view for our messages. What we have here is the body of our view. So this content is what is going to be placed wherever RenderBody is, so that's really easy. The second thing is that you can define sections. This is defining a section called scripts, and it is not required. So, Our views don't have to define a section called scripts. Now if required is true, then all of our views would have to have a section called scripts and you add a section by simply going @ section Scripts inside of your content page. And then anything defined inside of this @ section would end up wherever the render section call is made. So layout pages are very, very simple There also very useful. So we always want to use them. Now there's one other thing that we haven't talked about. And that is how does MVC know to use this underscore layout page for all of our views. Because we haven't specified them in any of ours views. And that is done inside of this _view start File. Here we have simply Layout = _layout. So, MVC whenever it is going to generate the HTML from a view, it's going to use this ViewStart first, that's why it's It's called ViewStart. And it's going to see that, okay, layout is set to _Layout. So for every view, it's going to use _Layout. So, pretty simple concepts there. But, we can't use our view component here because those three columns aren't defined in here. So the next place to go is inside of our home folder and then the index view. And if we scroll down, whenever we see a bunch of lists. Yes, here we go. We have the customize app. This application consists of, let's replace this run and deploy. Let's say that this is our latest messages and instead of having this unordered list, let's just comments this out just in case you just wanted to have that. We would want to invoke our component so we use @component. It has a method called Invoke and then we tell it what component that we want to invoke. In this case, it's LatestMessages and then since we have the amount of messages that we want to display, then we pass in that value. Now we don't have five messages, all we have are three messages. So we are just going to see three. But if we had more than five, then all we would see here is five. Now, of course, we could also modify Our view component, so that count is by default 5, in which case we can come back and just call the invoke method, passing in the name of that view component. That's a little more concise. So let's go back to the browser, let's refresh. Of course, behind the scenes, everything is going to be recompiled, but we have an error. It says it could not find an invoke method matching the parameters, so apparently we can't use a default value, so that's good to know. So let's change this to pass that value of five. Once again, let's go back to our invoke method. Let's take away the default parameter. I really thought that that would work, but apparently it doesn't. So let's refresh, we should see our home page, and here we have our latest messages. And you can see that they are ordered according to their date descending. And if we click on one of these titles then it's going to take us to the page for that message. So, a view component is very similar to a partial view. Except the main difference is that a view component is used to generate content for a view that really isn't related to that view component. Well, in the next lesson, we are going to add some API features to our message controller. Because it's nice that we have the web UI. Which is, you know, what we see in the browser. But it's also nice to allow other types of clients to retrieve message information. It's really easy to do, and we will do that in the next lesson.