[译]View components and Inject in ASP.NET MVC 6
原文: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类
- 创建一个文件夹名为ViewComponents. View component 类可以包含在任何文件夹下.
- 在ViewComponents 文件夹下常见一个类文件名为PriorityListViewComponent.cs.
- 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);
}
}
}
备注:
- 因为类名
PriorityListViewComponent以ViewComponent 结尾, 在视图中我们可以使用字符串"PriorityList". [ViewComponent]attribute 被使用来改变他的引用名. 例如, 我们有一个类名为XYZ, 我们应用ViewComponentattribute:[ViewComponent(Name = "PriorityList")]
public class XYZ : ViewComponent上面的[ViewComponent]attribute 告诉view component选择器当查找视图关联的component的使用 使用PriorityList, 在视图中使用字符串"PriorityList"来关联相应的类.- component使用构造函数注入.
Invoke 暴露一个方法在相应的视图中被调用, invoke可以包含任意参数. Invoke对应的异步方法是InvokeAsync
添加 view component view
- 在 Views\Todo 文件夹下面创建文件夹名为Components. 注意了必须名为Components.
- 在Views\Todo\Components 文件夹下面创建文件夹名为PriorityList. 这个文件夹的名字必须和view component 类的名字匹配, 或者类名的前缀匹配(如果类名使用
ViewComponent后缀). 如果你使用了ViewComponentattribute, 名字必须和attribute 名匹配. - 在 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> - 在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;
} }
}
更新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的数量, 完成的数量等.
- 创建一个文件夹名为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);
}
}
}
更新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>在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的更多相关文章
- ASP.NET MVC 6 一些不晓得的写法
今天在看 Scott Guthrie 的一篇博文<Introducing ASP.NET 5>,在 MVC 6 中,发现有些之前不晓得的写法,这边简单记录下,算是对自己知识的补充,有些我并 ...
- [转]ASP.NET MVC 入门5、View与ViewData
view在MVC模式中与用户进行最直接的接触,它负责数据的呈现.这里要注意一点就是,view只是负责数据的呈现,所以我们应该要尽量让view中不涉及业务逻辑的处理. 我们来添加一个Blog首页的vie ...
- ASP.NET MVC Overview
ASP.NET MVC Overview The Model-View-Controller (MVC) architectural pattern separates an application ...
- 【转】ASP.NET MVC 的最佳实践
[This post is based on a document authored by Ben Grover (a senior developer at Microsoft). It is ou ...
- ASP.Net Mvc 5 学习记录2015-9-9
我之前一直都是学习和开发都采用ASP.Net WebForm,对MVC的一直都是一知半解,最初以为ASP.Net WebForm的N层架构就是MVC.其实N层架构设计思想是"高内聚,低耦合& ...
- 自学MVC看这里——全网最全ASP.NET MVC 教程汇总
MVC架构已深得人心,微软也不甘落后,推出了Asp.net MVC.小编特意整理博客园乃至整个网络最具价值的MVC技术原创文章,为想要学习ASP.NET MVC技术的学习者提供一个整合学习入口.本文从 ...
- 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC
系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...
- 微冷的雨ASP.NET MVC之葵花宝典(MVC)
微冷的雨ASP.NET MVC之葵花宝典 By:微冷的雨 第一章 ASP.NET MVC的请求和处理机制. 在MVC中: 01.所有的请求都要归结到控制器(Controller)上. 02.约定优于配 ...
- 新作《ASP.NET MVC 5框架揭秘》正式出版
ASP.NET MVC是一个建立在ASP.NET平台上基于MVC模式的Web开发框架,它提供了一种与Web Form完全不同的开发方式.ASP.NET Web Form借鉴了Windows Form基 ...
随机推荐
- Python之禅+八荣八耻
Python之禅 (The Zen of Python):是Python语言的指导原则,可以在Python命令行输入import this显示. import this >>> Th ...
- Android成长日记-ContextMenu实现上下文菜单
一. ContextMenu的组成 标题以及标题图标 菜单内容 菜单内容的点击事件 二. ContextMenu与OptionMenu的区别 OptionMenu对应的是activity,一个acti ...
- Myeclipse 加载ojdbc14.jar步骤
目的:加载驱动程序,需要找到驱动的具体位置,就是找到其驱动的类名,Class.forName("oracle.jdbc.driver.OracleDriver");//加载并注册驱 ...
- CentOS加载U盘
概述: 把CentOS设置成了启动进入命令行,结果不知道在哪儿找U盘了,于是搜集了一些命令. 1. 查看分区信息,以确定那个是U盘 使用root执行fdisk -l,确定U盘是sdb1 2. 挂载U盘 ...
- 常用RSS订阅地址
随着Google Reader关门大吉,转战鲜果网了,RSS订阅地址经过几次折腾,丢的没剩几个了,写个文章记录一下吧,随时补充. --PS-- ,微信.微博之类的是社交平台,不能很好的梳理知识,一直用 ...
- Mysql 列转行统计查询 、行转列统计查询
-- ---------------------------- -- Table structure for `TabName` -- ---------------------------- D ...
- 01C语言基础知识
C语言知识要点总结 1在C语言中,关系运算的结果为“真”,就返回1,"假"就返回0 printf("input value is %d" , 5 > 4) ...
- python运维开发坎坷之路-01
前言 2014年9月,新疆乌鲁木齐,在51CTO学院看着alex老师的python教学视频,不得不说这是我第一次接触python这门高级语言,从最开始的一无所知到现在能够用python写脚本,再到未来 ...
- rhino(犀牛) --- color control
create color materials, if "材料赋予方式" is "图层", the color of "材质" is show ...
- 初学angular-简单的angular指令
实现一个简单的input清空内容,且清空对应ngModel 前台部分 <html ng-app="hpapp"> <head> <meta chars ...