原文:http://www.asp.net/vnext/overview/aspnet-vnext/vc

介绍view components

view components (VCs) 类似于partial views, 但是VCs更加强大. 可以简单的把VC想象成一个mini的控制器.当你认为使用partial太复杂的时候你可以考虑使用VCs,例如:

  • 动态导航菜单Dynamic navigation menus
  • 标签云(从数据库获取数据)
  • 登录面板
  • 购物车
  • 最近发布的文章
  • 博客的其它边栏

VC由两部分组成, 继承自ViewComponent的类和Razor视图.

View Component类可以通过下面的方式创建:

  • 继承ViewComponent.
  • [ViewComponent] attribute 装饰类, 或者继承在一个被[ViewComponent]装饰的类.
  • 创建一个类, 类名以ViewComponent结尾.

和控制器一样VCs必须是public的类.

添加view component类

  1. 创建一个文件夹名为ViewComponents. View component 类可以包含在任何文件夹下.
  2. ViewComponents 文件夹下常见一个类文件名为PriorityListViewComponent.cs.
  3. PriorityListViewComponent.cs 内容如下:
    using System.Linq;
    using Microsoft.AspNet.Mvc;
    using TodoList.Models; namespace TodoList.ViewComponents
    {
    public class PriorityListViewComponent : ViewComponent
    {
    private readonly ApplicationDbContext db; public PriorityListViewComponent(ApplicationDbContext context)
    {
    db = context;
    } public IViewComponentResult Invoke(int maxPriority)
    {
    var items = db.TodoItems.Where(x => x.IsDone == false &&
    x.Priority <= maxPriority); return View(items);
    }
    }
    }

备注:

  • 因为类名PriorityListViewComponentViewComponent 结尾, 在视图中我们可以使用字符串 "PriorityList".
  • [ViewComponent] attribute 被使用来改变他的引用名. 例如, 我们有一个类名为XYZ,  我们应用ViewComponent attribute:
    [ViewComponent(Name = "PriorityList")]
    public class XYZ : ViewComponent

    上面的[ViewComponent] attribute 告诉view component选择器当查找视图关联的component的使用 使用PriorityList, 在视图中使用字符串"PriorityList" 来关联相应的类.

  • component使用构造函数注入.
  • Invoke 暴露一个方法在相应的视图中被调用, invoke可以包含任意参数. Invoke对应的异步方法是InvokeAsync

添加 view component view

  1. 在 Views\Todo 文件夹下面创建文件夹名为Components. 注意了必须名为Components.
  2. Views\Todo\Components 文件夹下面创建文件夹名为PriorityList. 这个文件夹的名字必须和view component 类的名字匹配, 或者类名的前缀匹配(如果类名使用 ViewComponent 后缀). 如果你使用了ViewComponent attribute, 名字必须和attribute 名匹配. 
  3. 在 Views\Todo\Components\PriorityList 文件夹下创建Default.cshtml Razor视图文件 , 添加如下内容:
    @model IEnumerable<TodoList.Models.TodoItem>
    
    <h3>Priority Items</h3>
    <ul>
    @foreach (var todo in Model)
    {
    <li>@todo.Title</li>
    }
    </ul>
  4. views\todo\index.cshtml 文件中调用VC:
    @{
    ViewBag.Title = "ToDo Page";
    } <div class="jumbotron">
    <h1>ASP.NET vNext</h1>
    </div> <div class="row">
    <div class="col-md-4">
    @if (Model.Count == 0)
    {
    <h4>No Todo Items</h4>
    }
    else
    {
    <table>
    <tr><th>TODO</th><th></th></tr>
    @foreach (var todo in Model)
    {
    <tr>
    <td>@todo.Title </td>
    <td>
    @Html.ActionLink("Details", "Details", "Todo", new { id = todo.Id }) |
    @Html.ActionLink("Edit", "Edit", "Todo", new { id = todo.Id }) |
    @Html.ActionLink("Delete", "Delete", "Todo", new { id = todo.Id })
    </td>
    </tr>
    }
    </table>
    }
    <div>@Html.ActionLink("Create New Todo", "Create", "Todo") </div>
    </div> <div class="col-md-4">
    @Component.Invoke("PriorityList", 1)
    </div> </div>

    @await Component.InvokeAsync() 是对应的异步方法. 第一个参数是要调用的component的名字. 后面的参数是传到component类的参数.

注意: 一般来说View Component 视图加在Views\Shared 文件夹下, 因为VCs一般没有指定controller.

添加InvokeAsyn component

更新VC类如下:

using System.Linq;
using Microsoft.AspNet.Mvc;
using TodoList.Models;
using System.Threading.Tasks; namespace TodoList.ViewComponents
{
public class PriorityListViewComponent : ViewComponent
{
private readonly ApplicationDbContext db; public PriorityListViewComponent(ApplicationDbContext context)
{
db = context;
} // Synchronous Invoke removed. public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone)
{
string MyView = "Default"; // If asking for all completed tasks, render with the "PVC" view.
if (maxPriority > 3 && isDone == true)
{
MyView = "PVC";
} var items = await GetItemsAsync(maxPriority, isDone); return View(MyView, items);
} private Task<IQueryable<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)
{
return Task.FromResult(GetItems(maxPriority, isDone)); }
private IQueryable<TodoItem> GetItems(int maxPriority, bool isDone)
{
var items = db.TodoItems.Where(x => x.IsDone == isDone &&
x.Priority <= maxPriority); string msg = "Priority <= " + maxPriority.ToString() +
" && isDone == " + isDone.ToString();
ViewBag.PriorityMessage = msg; return items;
} }
}
注意: 同步的Invoke方法被移除了. 当调用数据库的时候使用异步InvokeAsync是最佳实践.

更新VC Razor视图如下 :

@model IEnumerable<TodoList.Models.TodoItem>

<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Title</li>
}
</ul>

最后, 更新views\todo\index.cshtml 视图文件:

    @* Markup removed for brevity. *@

    <div class="col-md-4">
@await Component.InvokeAsync("PriorityList", 2, true)
</div>
</div>

指定view的名字

一个复杂的VC可能会根据不同的条件指定使用非默认的视图. 下面的代码展示如何指定view的名字:

public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone)
{
string MyView = "Default"; // If asking for all completed tasks, render with the "PVC" view.
if (maxPriority > 3 && isDone == true)
{
MyView = "PVC";
} var items = await GetItemsAsync(maxPriority, isDone); return View(MyView, items);
}

复制 Views\Todo\Components\PriorityList\Default.cshtml 文件到Views\Todo\Components\PriorityList\PVC.cshtml . 改变PVC视图的内容以示区分:

@model IEnumerable<TodoList.Models.TodoItem>

<h2> PVC Named Priority Component View</h2>
<h4>@ViewBag.PriorityMessage</h4>
<ul>
@foreach (var todo in Model)
{
<li>@todo.Title</li>
}
</ul>

最后, 更新 Views\Todo\Index.cshtml :

@await Component.InvokeAsync("PriorityList",  4, true)

注入服务到视图中去

ASP.NET MVC 6 支持注入服务到视图中使用. 服务必须是非抽象和公开的. 在这个例子中, 我们穿件一个简单的类暴露todo的数量, 完成的数量等.

    1. 创建一个文件夹名为Services,添加一个名为StatisticsService.cs 的文件.

The StatisticsService class:

using System.Linq;
using System.Threading.Tasks;
using TodoList.Models; namespace TodoList.Services
{
public class StatisticsService
{
private readonly ApplicationDbContext db; public StatisticsService(ApplicationDbContext context)
{
db = context;
} public async Task<int> GetCount()
{
return await Task.FromResult(db.TodoItems.Count());
} public async Task<int> GetCompletedCount()
{
return await Task.FromResult(
db.TodoItems.Count(x => x.IsDone == true));
} public async Task<double> GetAveragePriority()
{
return await Task.FromResult(
db.TodoItems.Average(x =>
(double?)x.Priority) ?? 0.0);
}
}
}
  1. 更新Index视图. 在最上面添加如下注入语句:

    @inject TodoList.Services.StatisticsService Statistics

    在下面调用StatisticsService:

    <div>@Html.ActionLink("Create New Todo", "Create", "Todo") </div>
    </div> <div class="col-md-4">
    @await Component.InvokeAsync("PriorityList", 4, true) <h3>Stats</h3>
    <ul>
    <li>Items: @await Statistics.GetCount()</li>
    <li>Completed:@await Statistics.GetCompletedCount()</li>
    <li>Average Priority:@await Statistics.GetAveragePriority()</li>
    </ul>
    </div>
    </div>

    完整代码如下:

    @inject TodoList.Services.StatisticsService Statistics
    @{
    ViewBag.Title = "Home Page";
    } <div class="jumbotron">
    <h1>ASP.NET vNext</h1>
    </div> <div class="row">
    <div class="col-md-4">
    @if (Model.Count == 0)
    {
    <h4>No Todo Items</h4>
    }
    else
    {
    <table>
    <tr><th>TODO</th><th></th></tr>
    @foreach (var todo in Model)
    {
    <tr>
    <td>@todo.Title </td>
    <td>
    @Html.ActionLink("Details", "Details", "Todo", new { id = todo.Id }) |
    @Html.ActionLink("Edit", "Edit", "Todo", new { id = todo.Id }) |
    @Html.ActionLink("Delete", "Delete", "Todo", new { id = todo.Id })
    </td>
    </tr>
    }
    </table>
    }
    <div>@Html.ActionLink("Create New Todo", "Create", "Todo") </div>
    </div> <div class="col-md-4">
    @await Component.InvokeAsync("PriorityList", 4, true) <h3>Stats</h3>
    <ul>
    <li>Items: @await Statistics.GetCount()</li>
    <li>Completed:@await Statistics.GetCompletedCount()</li>
    <li>Average Priority:@await Statistics.GetAveragePriority()</li>
    </ul>
    </div>
    </div>
  2. Startup.cs 文件中注册StatisticsService类:

    // This method gets called by the runtime.
    public void ConfigureServices(IServiceCollection services)
    {
    // Add EF services to the services container.
    services.AddEntityFramework(Configuration)
    .AddSqlServer()
    .AddDbContext<ApplicationDbContext>(); // Add Identity services to the services container.
    services.AddDefaultIdentity<ApplicationDbContext, ApplicationUser, IdentityRole>(Configuration); // Add MVC services to the services container.
    services.AddMvc(); services.AddTransient<TodoList.Services.StatisticsService>();
    }
 

[译]View components and Inject in ASP.NET MVC 6的更多相关文章

  1. ASP.NET MVC 6 一些不晓得的写法

    今天在看 Scott Guthrie 的一篇博文<Introducing ASP.NET 5>,在 MVC 6 中,发现有些之前不晓得的写法,这边简单记录下,算是对自己知识的补充,有些我并 ...

  2. [转]ASP.NET MVC 入门5、View与ViewData

    view在MVC模式中与用户进行最直接的接触,它负责数据的呈现.这里要注意一点就是,view只是负责数据的呈现,所以我们应该要尽量让view中不涉及业务逻辑的处理. 我们来添加一个Blog首页的vie ...

  3. ASP.NET MVC Overview

    ASP.NET MVC Overview The Model-View-Controller (MVC) architectural pattern separates an application  ...

  4. 【转】ASP.NET MVC 的最佳实践

    [This post is based on a document authored by Ben Grover (a senior developer at Microsoft). It is ou ...

  5. ASP.Net Mvc 5 学习记录2015-9-9

    我之前一直都是学习和开发都采用ASP.Net WebForm,对MVC的一直都是一知半解,最初以为ASP.Net WebForm的N层架构就是MVC.其实N层架构设计思想是"高内聚,低耦合& ...

  6. 自学MVC看这里——全网最全ASP.NET MVC 教程汇总

    MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要学习ASP.NET MVC技术的学习者提供一个整合学习入口.本文从 ...

  7. 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  8. 微冷的雨ASP.NET MVC之葵花宝典(MVC)

    微冷的雨ASP.NET MVC之葵花宝典 By:微冷的雨 第一章 ASP.NET MVC的请求和处理机制. 在MVC中: 01.所有的请求都要归结到控制器(Controller)上. 02.约定优于配 ...

  9. 新作《ASP.NET MVC 5框架揭秘》正式出版

    ASP.NET MVC是一个建立在ASP.NET平台上基于MVC模式的Web开发框架,它提供了一种与Web Form完全不同的开发方式.ASP.NET Web Form借鉴了Windows Form基 ...

随机推荐

  1. PHP框架中的日志系统

    现在在一家公司做PHP后台开发程序猿(我们组没有前端,做活动时会做前端的东西),刚开始到公司的时候花2个周赶出了一个前端加后台的活动(记得当时做不出来周末加了两天班...),到现在过去4个多月了,可以 ...

  2. 事务块TransactionScope使用

    TransactionScope 可以让代码块成为事务性代码块. 当发生异常时,会自动回滚.后期手动提交事务. 简单的例子: using (TransactionScope ts = new Tran ...

  3. python中%和format

    两者都是格式化字符串用的,前者是比较老的版本,现在已经不推荐,后者更强大一些 % In [22]: print '%s' % 'hello world' hello world In [23]: pr ...

  4. JZOJ P1847:找01串

    传送门 DP预处理+贪心 首先设$f[i][j]$表示长度为$i$的01串中有不大于$j$个1,然后显然 $f[i][j]=\sum_{k=1} ^{j} C[i][k]$ $C[i][j]=C[i- ...

  5. mac OS(OS X)的OI编译环境配置指南

    编译环境:gdb+Atom 如何安装gdb: http://logic0.blog.163.com/blog/static/1889281462014183271283/   Atom下载地址: ht ...

  6. python redis使用心得

    发布与订阅 连接池代码 redis_conn.py import redis REDIS_CONN = { 'HOST': '192.168.1.11', 'PORT': '6378', 'DB': ...

  7. DNS(企业级)

    构建DNS(企业级) 1.硬件选型 CPU:12C以上配置 内存:16G 网络:千兆 2.初始化系统配置 关闭 iptables service iptables stop chkconfig ipt ...

  8. SVM支持向量机的高维映射与核函数-记录毕业论文2

    上一篇博客将了在数据集线性可分的情况下的支持向量机,这篇主要记录如何通过映射到高维解决线性不可分的数据集和如何通过核函数减少内积计算量的理论思想. [5]径向基函数的核函数:https://www.q ...

  9. Java——不弹起的按钮组件:JToggleButton

    import java.awt.GridLayout; import javax.swing.JFrame; import javax.swing.JToggleButton; //========= ...

  10. 股市非常态,CCI指标买卖点实例图解

    CCI指标即顺势指标,是唐纳德·蓝伯特于上世纪80年代提出的,是一种比较新颖的技术指标.CCI指标是专门用来衡量股价是否超出常态分布范围,是一种 超买超卖类指标,但它与其他超买超卖型指标又有自己比较独 ...