Instructor-led online courses in ASP.NET Core, ASP.NET MVC, and ASP.NET Design Patterns. Read more...
Instructor-led online courses in ASP.NET Core, ASP.NET MVC, and ASP.NET Design Patterns. Conducted by Bipin Joshi on weekends. More details are available here.

Create View Components in ASP.NET Core

ASP.NET Core offers several ways to reuse your code and UI. One of them is View Components. Simply put a view component is a bundle of C# code, Razor code, and markup that occupies some screen real-estate. Unlike partial views a view component is more like a standalone widget housed in a view.

A view component consists of two main pieces :

  • A class that inherits from ViewComponent base class and contains the processing logic of the view component
  • A razor view that represents the UI of the view component

Notice  that a custom tag helper exists as a C# class. A partial view exists as a razor view. A view component, on the other hand, consists of a C# class as well as a razor view.

In order to understand how to create and consume a view component, we will create a Latest Orders view component as shown below :

The table that lists latest orders for a specific CustomerID from the Northwind database is actually a view component. Once created you can reuse that view component in any view of the application.

Ok. Now let's create the Latest Orders view component.

Creating the NorthwindDbContext and Order entity class

Begin by creating a new ASP.NET Core web application as you normally do. Then add DataAccess folder under the project root. This folder will contain the DbContext and Order entity class. These classes are shown below :

[Table("Orders")]
public class Order
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int OrderID { get; set; }
    public string CustomerID { get; set; }
    public DateTime OrderDate { get; set; }
    public string ShipCountry { get; set; }
}
public class NorthwindDbContext:DbContext
{

    public NorthwindDbContext
(DbContextOptions<NorthwindDbContext> options) 
: base(options)
    {

    }

    public DbSet<Order> Orders { get; set; }
}

As you can see, the Order class maps to the Orders table of the Northwind database and contains four public properties namely OrderID, CustomerID, OrderDate, and ShipCountry. The NorthwindDbContext inherits from DbContext base class and contains the Orders DbSet.

Once the NorthwindDbContext is created, you can register it with the DI container in the ConfigureServices() method. The ConfigureServices() method is shown below :

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddEntityFrameworkSqlServer();

    services.AddDbContext<NorthwindDbContext>
(o => o.UseSqlServer("data source=.;
initial catalog=Northwind;integrated security=true;
multipleactiveresultsets=true;"));

}

Make sure to change the database connection string as per your setup.

Creating the Latest Orders view component

Now add ViewComponents folder under the project root folder. We will use this folder to place our view component class files. The folder name, of course, can be anything of your choice.

Then add a class in the ViewComponents folder named LatestOrdersViewComponent and write the following code into it :

public class LatestOrdersViewComponent : ViewComponent
{
    private NorthwindDbContext db;


    public LatestOrdersViewComponent(NorthwindDbContext db)
    {
        this.db = db;
    }


    public IViewComponentResult Invoke
(int count = 10, string customerid = "")
    {
        IQueryable<Order> query = db.Orders;

        if (!string.IsNullOrWhiteSpace(customerid))
        {
            query = db.Orders.Where
(o => o.CustomerID == customerid);
        }

        query = query.OrderByDescending
(o=>o.OrderDate).Take(count);

        List<Order> model = query.ToList();

        return View(model);
    }
}

The LatestOrdersViewComponent class inherits from ViewComponent base class. It has a public constructor that receives a NorthwindDbContext object for the sake of database operations. More importantly, it contains the Invoke() method that does the processing of the view component. The Invoke() method is where the processing logic of your view component will go. And it can take parameters depending on your requirement. In this example, the Invoke() method accepts two parameters - count and customerid. The former parameter indicates the number of latest orders to be displayed and the later indicates a CustomerID whose latest orders are to be displayed.

Watch this video for code demonstration

Inside, the Invoke() method simply fetches the data using the NorthwindDbContext and Orders DbSet. Notice that the Invoke() returns IViewComponentResult. By default, the View() method returns a view named Default.cshrml but you can specify a custom view name as the first parameter of the View() method.

return View("MyView",model);

You can also pass a model to the Default.cshtml view as we have done in the above implementation.

Now we need to create the Default.cshtml view. The Default.cshtml is typically placed in the following location :

Notice that Default.cshtml resides under View > Shared > Components > LatestOrders folder where LatestOrders is the name of the view component class without "ViewComponent".

The Default.cshtml renders a table containing the list of orders and is shown below :

@model List<ViewComponentDemo.DataAccess.Order>


<table border="1" cellpadding="10">

    @foreach(var item in Model)
    {
        <tr>
            <td>@item.OrderID</td>
            <td>@item.CustomerID</td>
            <td>@item.OrderDate</td>
            <td>@item.ShipCountry</td>
        </tr>

    }

</table>

This completes our Latest Orders view component. Now, let's use it in some view.

Using a view component on a view

Add HomeController with the default Index() action in the Controllers folder and Index.cshtml under Views > Home folder. The Index.cshtml is shown below :

<h1>Latest orders are shown below :</h1>

@await Component.InvokeAsync
("LatestOrders", new { count = 10, customerid = "ALFKI" })

The Component.InvokeAsync() method does the job of invoking the Invoke() of the view component. It takes two parameters. The first parameter is the name of the view component class (LatestOrders in this case) and the second parameter is an anonymous object wrapping all the parameters of the Invoke() method. In this case we set count to 10 and customerid to ALFKI.

If you navigate to the Home/Index you should see the latest orders displayed in a table as shown at the beginning of this article.

Using a view component as a tag helper

You can also use a view component as a tag helper. In order to do so you first need to register it in the _ViewImports.cshtml file :

@addTagHelper *, ViewComponentDemo

Here, ViewComponentDemo is the project's assembly name.

You can then use the LatestOrders view component like this :

<vc:latest-orders count="10" customerid="ALFKI"></vc:latest-orders>

Notice how a tag prefix of vc have been used above. Also notice how the class name (LatestOrders) is written as latest-orders in the tag markup. The Invoke() method's parameters are now passed using the corresponding attributes - count and customerid.

If you add the above markup in the Index.cshtml you will get another table with latest orders :

Using a view component in an action

In most of the cases a view component is housed somewhere in a view. However, if you wish you can return a view component from a controller's action as if it is a view.

public class HomeController : Controller
{

    public IActionResult Index()
    {
        return ViewComponent
("LatestOrders", new { count = 10, customerid = "ALFKI" });
    }

}

As you can see, the above code uses ViewComponent() method of the Controller base class to return the output of a view component. The ViewComponent method essentially accepts the same parameters as the Component.InvokeAsync() method.

The following figure shows a sample run of the above method.

Notice that the heading mentioned in the Index.cshtml is no longer displayed because the content of LatestOrders view component are directly rendered using the ViewComponent() method.

Using view components in razor pages

In the above example, you used the Latest Orders view component in an ASP.NET Core MVC application. However, you can also use them on razor pages. Have a look at the Index.cshtml razor page added under Pages folder.

To display the Latest Orders view component on this razor page you can use the following code / markup :

@page
@model ViewComponentDemo.Pages.IndexModel

<h1>Welcome from Razor Pages!</h1>

@await Component.InvokeAsync("LatestOrders", 
new { count = 10, customerid = "ALFKI" })

<hr />

<vc:latest-orders count="10" customerid="ALFKI"></vc:latest-orders>

The output of Index.cshtml razor page should resemble to that of Index.cshtml view seen earlier.

That's it for now! Keep coding !!


Bipin Joshi is a software consultant, trainer, author and spiritual yoga mentor having 23+ years of experience in software development. He teaches online training courses in ASP.NET Core, Angular, and Design Patterns to individuals and small groups. He is a published author and has authored or co-authored books for Apress and Wrox press. Having embraced the Yoga way of life he also teaches Ajapa Yoga to interested individuals. To know more about him click here.

Get connected : Twitter  Facebook  Google+  LinkedIn

Posted On : 05 March 2018


Tags : ASP.NET ASP.NET Core MVC Architecture C#


Subscribe to our newsletter

Get monthly email updates about new articles, tutorials, code samples, and how-tos getting added to our knowledge base.