View components are a new feature introduced in ASP.NET Core, they are almost similar to Partial Views but is more powerful. When you use Partial Views, you have dependency over the Controller. However, when you use the ViewComponent
attribute, you do not have to depend on the Controller, so we will establish separation of concerns and have better testability. Even though the existing Partial View HTML helper is still supported, it is preferable to use the View component whenever you want to show a reusable piece of information when you are using .NET Core.
You can create a ViewComponent
using any of the following:
ViewComponent
attribute[ViewComponent]
attribute or derive it from the class that has the [ViewComponent]
attributeViewComponent
attributeWhatever option you choose, this ViewComponent
should be public, non-nested, and non-abstract classes.
Like Controllers, you can use the Dependency Injection (via a constructor) in the ViewComponent
attribute as well. As the ViewComponent
attribute is separate from the Controller lifecycle, you may not be able to use the action filters in ViewComponents
.
There is a method called Invoke
(or InvokeAync
, the asynchronous equivalent of Invoke
), that will return the IComponentViewResult
interface. This method is similar to the action method of the Controller that will return the View.
Let's get our hands dirty by creating a ViewComponent
attribute.
Create a new folder called ViewComponents
in your project and a new class called SimpleViewComponent
, as shown in the following screenshot:
The SimpleViewComponent
file that we created will look like the following:
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNet.Mvc; namespace Chapter4.ViewComponents { public class SimpleViewComponent :ViewComponent { public IViewComponentResult Invoke() { var data = GetSampleData(); return View(data); } /// <summary> /// This is a simple private method to return some dummy data /// </summary> /// <returns></returns> private List<string> GetSampleData() { List<string> data = new List<string>(); data.Add("One"); data.Add("Two"); data.Add("Three"); return data; } } }
We just have a couple of methods, one to populate the data and the other is the Invoke
method where we will render the View.
Once you have created the ViewComponent
attribute, you will need to include the ViewComponent
namespace in the Views\_ViewImports.cshtml
file so that the ViewComponents
attributes can be available for all the Views. The highlighted code snippet in the following is added to the View:
@using Chapter4
@using Chapter4.Models
@using Chapter4.ViewComponents
@addTagHelper "*, Microsoft.AspNet.Mvc.TagHelpers"
We have created the ViewComponent
and made them available to all of the Views. A simple action method in the HomeController
file just returns the View:
public ActionResult Sample() { return View(); }
In the associated View, we can just invoke the component as shown in the following code snippet:
<p> This is a sample web page <br/> <div> @Component.Invoke("Simple") </div> </p>
When you invoke the component, it will search in the following two folders:
Views<controller_name>Components<view component name><view name>
folderViewsSharedComponents<view_component_name>/<view_name>
folderThe default View name of the View component is Default
, which makes your file name for the View Default.cshtml
. So, we will need to create the Default.cshtml
file in ViewsSharedSimpleDefault.cshtml
folder, as shown in the following screenshot:
In the the View (Default.cshtml
file) of the ViewComponent
file, we are just iterating the items in the model and displaying them as an unordered list item, as shown in the following code:
@model IEnumerable<string> <h3> Sample list</h3> <ul> @foreach(var item in Model) { <li>@item</li> } </ul>
When you run the application and access the URL (http://localhost:50132/Home/Sample
), you should see the following output:
The first line, This is a sample web page, comes from the parent View file (sample.cshtml
) whereas the subsequent list comes from ViewComponent
attribute.
The ViewComponent
attributes are usually referred in the Views. However, if you want to call the ViewComponent
directly from your Controller, you can do so.
I have called the Sample
action method to call the Simple ViewComponent
directly instead of calling it through some other View as follows:
public ActionResult Sample() { return ViewComponent("Simple"); //return View(); }
Thus, these ViewComponents
have far more flexibility and features, such as Dependency Injection, when compared to old HTML Partial Views. This ensures ViewComponents
are separately tested.