ASP.NET Core    View Components     MVC  
▌Introduction
In my opinion,
View Components is very similar to Partial View in rendering them
to the HTML. However, View Components executes the InvokeAsync
function before passing a model to the View. (We will talk about this later.)  
▋Not reachable directly as an HTTP
endpoint, they are invoked from your code (usually in a view). A view component
never handles a request.
▋View component classes can be
contained in any folder in the project.
▋It can uses dependency injection.
▋InvokeAsync exposes a method which
can be called from a view, and it can take an arbitrary number of arguments.
▌Environment
▋Visual Studio 2015
Update 3
▋NPM: 3.10.3                                     
▋Microsoft.AspNetCore.Mvc
1.0.0
▌Implement
▋Create controller/view
Before we deep into View Components, create the
controller and view as following.
▋CustomerVcController
| 
[Area("Basic")] 
[Route("Basic/[controller]/[action]")] 
public class CustomerVcController : Controller 
{ 
        public IActionResult Index() 
        { 
            return View(); 
        } 
} | 
We will implement View later.
▋ViewComplonent : Default view
We could create the Default view in either 
Views\CustomerVc\Components\[View Component
name]\Default.cshtml
Or 
Views\Shared\Components\[View Component name]\Default.cshtml
The View Component will return the Default.cshtml as View in default.
▋ Default.cshtml
| 
@model List<Angular2.Mvc.Core.Models.ViewModel.VmCustomer> 
<div class="alert alert-info" role="alert"> 
    @{ 
        var title = "Hi, " + ViewBag.Description; 
    } 
    @title 
</div> 
<table class="table table-bordered table-hover"> 
    <thead> 
        <tr> 
            <th> 
                @Html.DisplayNameFor(model
  => model.First().Name) 
            </th> 
            <th> 
                @Html.DisplayNameFor(model
  => model.First().Age) 
            </th> 
            <th> 
                @Html.DisplayNameFor(model
  => model.First().Phone) 
            </th> 
            <th> 
                @Html.DisplayNameFor(model
  => model.First().Description) 
            </th> 
            <th></th> 
        </tr> 
    </thead> 
    <tbody> 
        @if (Model != null) 
        { 
            foreach (var item in Model) 
            { 
                <tr> 
                   
  <td class="col-sm-2"> 
                       
  @(new
  Microsoft.AspNetCore.Html.HtmlString(item.Name)) 
                   
  </td> 
                   
  <td class="col-sm-2"> 
                       
  @Html.DisplayFor(modelItem
  => item.Age) 
                   
  </td> 
                   
  <td class="col-sm-1"> 
                       
  @Html.DisplayFor(modelItem
  => item.Phone) 
                   
  </td> 
                   
  <td class="col-sm-2"> 
                       
  @Html.DisplayFor(modelItem
  => item.Description) 
                   
  </td> 
                </tr> 
            } 
        } 
    </tbody> 
</table> | 
▋ViewComplonent : class
Notice that ViewComponent
classe can be put in any folder in the project.
I put it in the path just
like controllers and views.
▋CustomerViewComponent.cs
| 
[ViewComponent(Name = "CustomerVc")] 
public class CustomerViewComponent : ViewComponent 
{ 
        public async Task<IViewComponentResult> InvokeAsync(int? id, string name) 
        { 
            var items = await this.getCustomersAsync(id,
  name); 
           
  ViewBag.Description = "this view is
  from ViewComponent."; 
            return View(items); //Return Default.cshtml 
        } 
        private async Task<List<VmCustomer>>
  getCustomersAsync(int? id, string name) 
        { 
               //return something 
        } 
} | 
PS.
The
ViewComponent name is “Customer” with the suffix “ViewComponent” of “CustomerViewComponent”
being removed.
We can specify the ViewComponent name by the Attribute: 
[ViewComponent(Name = "")]
Okay, we had implemented the ViewComponent, let us see
how to use it in View or Controller.
▋Use ViewComponent in View
▋index.cshtml
| 
@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
<div> 
    @await Component.InvokeAsync("CustomerVc", new { name = "JB" }) 
</div> | 
Notice that
View Components are still RENDERED ON SERVER SIDE, we will later use another
way to render it in ajax way.
▋OR use ViewComponent in Controller
| 
public IActionResult IndexVc() 
{ 
   return ViewComponent("CustomerVc", new { name = "JB" }); 
} | 
▋Result
▋ViewComplonent : Return different view
Before the ViewComponent
return a view, we invoke the InvokeAsync() function.
So we could implement some
logics inside the ViewComponent. 
Here is a simple application,
we will let ViewComponent return different view which depending on the
parameter value. 
First we should create
another view for our ViewComponent.
And then update ViewComponent
class.
▋CustomerVcController.cs
(Update)
| 
public async Task<IViewComponentResult> InvokeAsync(string display, int? id, string name) 
{ 
      var items = await this.getCustomersAsync(id,
  name); 
      ViewBag.Description
  = "this view is from
  ViewComponent."; 
      if (!string.IsNullOrEmpty(display)
  && display.ToLower().Equals("card")) 
                return View("Card",
  items); 
      else 
                return View("Default", items); 
} | 
▋Index.cshtml
(Update)
| 
@{ 
    Layout = "~/Views/Shared/_Layout.cshtml"; 
} 
<div> 
    @await
  Component.InvokeAsync("CustomerVc", new {display="Card",  name = "JB" }) 
</div> | 
▋Result
▋Ajax rendering
We can create a Http method
in Controller and just return the view (HTML) thru ViewComponent. (Just like
returning PartialView!)
▋Controller
| 
[HttpGet] 
public IActionResult GetView([FromQuery] string name) 
{ 
   return ViewComponent("CustomerVc", new { name = "JB" }); 
} | 
▋Index.cshtml
| 
<div id="ajaxCust"></div> | 
▋javascript (jquery)
| 
$(function () { 
   
  renderViewComponent(); 
    function renderViewComponent()
  { 
        $("#ajaxCust").html(""); 
        $.ajax({ 
           
  dataType: "html", 
            url:
  getUri + "?name=Leia", 
           
  success: function (cust) { 
                $("#ajaxCust").append(cust); 
            } 
        }) 
    } 
}) | 
▋Result
▌Reference








 
沒有留言:
張貼留言