Author : MD TAREQ HASSAN
What is a View Component
- A view component is a C# class that provides a partial view independently from the parent view and the action that renders it
 - A view component can be thought of as a specialized action, but one that is used only to provide a partial view with data; it cannot receive HTTP requests, and the content that it provides will always be included in the parent view
 - A view component:
    
- Renders a chunk rather than a whole response
 - Includes the same separation-of-concerns and testability benefits found between a controller and view
 - Can have parameters and business logic
 - Is typically invoked from a layout page
 
 - View components don’t use model binding, and only depend on the data you provide when calling into it
 - View components have their own controllers (consider ViewComponent is standalone MVC in the way area can be considered Mini MVC)
 - View component allows to have full separation of concerns and makes view components much easier to unit test
 - Like controllers, view components must be public, non-nested, and non-abstract classes
 - A view component class:
    
- Fully supports constructor dependency injection
 - Does not take part in the controller lifecycle, which means you can’t use filters in a view component
 
 - View component views must be placed in a folder named Components
 - If your view component needs to be used with many controllers, it should be placed in the 
Views\Shared\Componentsfolder (otherwise, it can be placed as a subfolder under the Views folder for the target controller) - Links:
    
- https://aspnetcore.readthedocs.io/en/stable/mvc/views/view-components.html
 - https://docs.microsoft.com/en-us/aspnet/core/mvc/views/view-components
 - https://medium.com/@jpdeffo/asp-net-core-razor-tag-helper-and-view-components-inside-a-container-3cb007001535
 - https://www.cazton.com/blogs/technical/view-components-in-asp-net-core
 
 
Resolving view component view
View component is resolved in the same way razor views are resolved for controller actions - by convention
ViewComponents/{Foo}ViewComponent.cs(‘ViewComponents’ folder is in project root folder, folder name can be anything, named ‘ViewComponents’ as good practice)Views/Shared/Components/{Foo}/Default.cshtml(folder name ‘Components’ is mandatory since ViewComponent view will be resolved by convention)Default.cshtml=>Defaultis used for the view name by convention- To use view name other than ‘Default’ => https://aspnetcore.readthedocs.io/en/stable/mvc/views/view-components.html#specifying-a-view-name
 
Creating ViewComponent
- A view component class can be created by any of the following:
    
- Deriving from ViewComponent
 - Decorating a class with the [ViewComponent] attribute, or deriving from a class with the [ViewComponent] attribute
 - Creating a class where the name ends with the suffix ViewComponent
 - Fully supports constructor dependency injection
 - Doesn’t take part in the controller lifecycle, which means you can’t use filters in a view component
 
 - All view component parameters are required
 - Links:
 
ViewComponent class: ViewComponents/SpeakerCardViewComponent.cs
using Microsoft.AspNetCore.Mvc;
using WebAppTagHelper.Models;
namespace WebAppTagHelper.ViewComponents
{
    public class SpeakerCardViewComponent : ViewComponent
    {
        public IViewComponentResult Invoke(Speaker speaker)
        {
            return View(speaker);
        }
    }
}
ViewComponent view: Views/Home/Components/SpeakerCard/Default.cshtml
@model WebAppTagHelper.Models.Speaker
<div class="col-xs-12 col-sm-6 col-md-4 col-lg-3">
    <div class='card'>
        <div class='card-img'>
            <img src='static/speakers/Speaker-@(Model.SpeakerId).jpg' />
        </div>
        <h4 class='card-title'>
            <a href='#'>@(Model.UserFirstName) @(Model.UserLastName)</a>
        </h4>
        <p class='card-position'>@(Model.Company)</p>
        <p class='card-description'>Session time to be announced</p>
        <ul class='social'>
            <li>
                <a target='_blank' href='#'>LinkedIn</a>
            </li>
            <li>
                <a target='_blank' href='#'>Microsoft</a>
            </li>
        </ul>
    </div>
</div>
Invoking a view component
From view: Component.InvokeAsync(...)
<div class="container">
    <speaker-track track-name="JavaScript">
        @await Component.InvokeAsync("SpeakerCard", speakers[0])
        @await Component.InvokeAsync("SpeakerCard", speakers[1])
        @await Component.InvokeAsync("SpeakerCard", speakers[2])
    </speaker-track>
</div>
From view: tag helper syntax (must use prefix vc:)
<div class="container">
    <speaker-track track-name="JavaScript">
        <vc:speaker-card speaker=@speakers[0]></vc:speaker-card>
        <vc:speaker-card speaker=@speakers[1]></vc:speaker-card>
        <vc:speaker-card speaker=@speakers[2]></vc:speaker-card>
    </speaker-track>
</div>
From controller
public IActionResult IndexVC()
{
  return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });
}
Details: https://aspnetcore.readthedocs.io/en/stable/mvc/views/view-components.html#invoking-a-view-component