ASP.NET Core 十种方式扩展你的 Views
原文地址:http://asp.net-hacker.rocks/2016/02/18/extending-razor-views.html
作者:Jürgen Gutsch
翻译:杨晓东(Savorboard)
现在,已经有很多种方式来扩展Razor视图了,我们循循渐进,先从最简单的开始。
如果你之前熟悉MVC5(以及之前的MVC)中的视图的话,有一部分你应该已经很熟悉了。在新的ASP.NET Core 中,那些你熟悉的方式有一部分仍然能用,只是Core版本针对视图又添加了一些东西。这篇文章,我们就来一起看看吧。
#1:数据视图(Typed Views)
这是一个不具有动态内容的最基本的一个视图,就是你定义一个ViewModel , 然后ViewModel具有一些默认值,在视图上直接呈现而已。定死的ViewModel,好像不是很常见,以至于你使用Visual Studio新建一个默认的Web应用程序的话,都看不到它。它就看起来像一个*.cshtml
结尾的HTML文件,但是,cshtml文件却是服务端可以解析的一种文件,所以你可以在里面使用一些Razor语法,比如HtmlHelpers,UrlHelpers等。同样,你可以使用ViewBag
或者ViewData
来从Controller的Action传输数据到View里面,来让它具有动态的内容。但是ViewBag
和ViewData
都是弱类型的,所以没有智能提示,用起来略不爽。
要在你的视图中使用强类型数据对象,你需要定义一个Model来在视图中使用。
@model ExtendViews.ViewModels.AboutModel
<!-- usage: --->
@Model.FullName
这种方式是不是很常见的? 下一种方式是一个更好的方式来布局我们的视图:
#2:布局(Layouts):
相当于ASP.NET的WebForms的母版页,不过它是定义Razor视图的基本布局的一种方式。它就是_Layout.cshtml
, 位于 Views\Shared\ 文件夹里 。通常情况下这个文件通常包含HTML的header,body和公用的一些东西。你可以多建几个互相进行组合,来完成整个站点的布局。其他页面引用布局视图页的时候,是这样子写的(注意不需要扩展名):
@{
Layout = "_Layout";
}
此调用需要在您的视图的第一行中。但你不需要在每一个视图中定义布局,如果你使用Visual Studio新建一个ASP.NET Core项目,Views文件夹有一个_ViewStart.cshtml
,在运行的时候它会自动的导入到每个视图中去。
在_Layout.cshtml
有一个方法法叫 RenderBody()
,它就是用来渲染详细的视图页到模板布局视图中:
@RenderBody()
在此方法的位置,详情视图就会被渲染到这里。
#3: 区域(Sections)
有时候子视图中想在主视图中显示一部分html代码,比如javascript代码或者是css,这个时候就可以使用Sections,通常情况下在页面的结尾部分。
在主视图中(_Layout.cshtml
)定义一个Javascripts Section:
@RenderSection("scripts", required: false)
有一个required参数来声明这个Section是否必须的。然后你就可以在子视图中这样使用:
@section scripts
{
<script>
$(function() {
// some more js code here;
});
</script>
}
如果你使用嵌套的布局,你可能需要嵌套这个区域。意思就是你在Section里面嵌套调用 RenderSection()
:
@section scripts
{
@RenderSection("scripts", required: false)
}
#4: 分部视图( PartialViews)
你可以提取html页面中重用的部分,把它放到一个新的Razor视图中,这个视图没有自己的Action,这种视图就叫做分部视图。 分部视图通常也在Views\Shard\
文件夹。
分部视图同样也可以是一个数据视图,它可以从父视图中获取数据(但不是必须的):
@model IEnumerable<UserModel>
@if (Model.Any())
{
<ul>
@foreach (var user in Model)
{
<li>@user.FullName</li>
}
</ul>
}
这个分部视图需要从父视图中获取用户列表的数据
@{ await Html.RenderPartialAsync("Users", Model.Users);}
如果你的分部视图没有定义用户模型,你就不需要传第二个参数。
#5:视图组件(ViewComponents)
这个 ASP.NET Core特有的。
译者注:类似于以前的用户控件
有时候你需要做一些分部视图的事情,但是又包含一些业务逻辑在里面。在过去,你可以使用ChildAction渲染结果到一个视图中,但是,在 ASP.NET Core中,有一种新的方式来做这件事情,它就是ViewComponents
(我已经写了一篇关于ViewComponents的博文)。它类似于在MVC中的一种迷你的MVC,也就是说他们可以有自己的Controller,和单个的action以及view。ViewComponents
是完全独立于你的当前视图的,但是可以通过你当前的视图传输数据。
想这样调用它,来渲染一个ViewComponents
:
@Component.Invoke("Top10Articles");
可以看我的博客来学习怎么创建自己的ViewComponent
。
#6: HTML助手(HtmlHelpers)
在HTMLHelper
类中,你可以创建你自己的扩展方法来扩展Razor语法:
public static class HtmlHelperExtensions
{
public static HtmlString MyOwnHtmlHelper(this HtmlHelper helper, string message)
{
return new HtmlString($"<span>{message}<span>");
}
}
在你的视图中,创建一个可重用的部分是非常有用的,它比分部视图多包含了一些业务逻辑。比HTMLHelpers扩展更好的是新的TagHelpers,但是在扩展你视图的时候,HTMLHelpers仍然有它自己的一些适用的地方。
#7: 标签助手(TagHelper)
这是 ASP.NET Core 非常好的一个新特性。
一个扩展你视图的小助手,它看起来像一个原生的HTML标签一样。 在ASP.NET Core MVC中你应该使用 TagHelpers 来替换 HtmlHelpers,因为它们更加的简洁和容易使用。另一个巨大的好处就是依赖注入,在HtmlHelpers中是使用不了的,因为HtmlHelpers 扩展的都是静态内容。 但TagHelpers是一个公共类,我们可以很容易的在它的构造函数中注入服务。
下面是一个很简单的小示例,来展示怎么样定义一个TagHelper:
[TargetElement("hi")]
public class HelloTagHelper : TagHelper
{
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "p";
output.Attributes.Add("id", context.UniqueId);
output.PreContent.SetContent("Hello ");
output.PostContent.SetContent(string.Format(", time is now: {0}",
DateTime.Now.ToString("HH:mm")));
}
}
这里定义了一个叫做hi
的标签,它以HTML标记来呈现,p标签的内容是当前时间。
使用:
<hi>John Smith</hi>
结果:
<p>Hello John Smith, time is now: 18:55</p>
ASP.NET Core MVC 已经默认提供了很多TagHelpers来替换以前的HtmlHelpers。例如ActionLink已经被新的TagHelper所替换:
@Html.ActionLink(“About me”, “About”, “Home”)
新的TagHelper像这样来创建一个link:
<a asp-controller=”Home” asp-action=”About”>About me</a>
以上两种方式来创建一个a标签的结果:
<a href=”/Home/About”>About me</a>
可以看到,TagHelpers看起来更像原生的HTML,他们在视图中更加的直观,更高的可读性,并且更容易使用。
#8: 依赖注入(Dependency Injection)
这也是ASP.NET Core的新特性。
在扩展你的视图的时候,可以使用依赖注入了,这是一个非常大改进。是的,你可以在你的视图中使用DI了。
在StackOverflow和reddit有人这样问?
这真的有意义吗? 这不是会搞乱我的视图吗? 这不是与MVC模式背离吗?
我认为,不是这样的。 的确,在真正需要的地方你才使用,并且,你使用的时候需要非常小心。 有这样一个有效的场景:你创建一个表单来编辑用户的资料信息(User Profile), 用户可以添加他的公司位置,地址, 国家城市等等,我不愿意从Action到View中传输公司位置 ,地址和国家城市。我只愿意通过用户资料本身(User Profile), 我只想在 Action 中处理用户资料(User Profile)。这时候可以注入服务来给我查询数据,这就是为什么这种情况下它是非常有用的。它可以让我们的Action和ViewModel 保持非常的干净。
在Startup.cs
中的ConfigureServices
来注册你具体的服务,然后你就可以在视图中这样来使用,只需要一行代码:
@inject DiViews.Services.ICountryService CountryService;
现在你可以在你的视图中使用ContryService
来填充国家下拉列表。
我在这篇博客中写了很多关于依赖注入的博文。
#9: 函数(Functions)
在一个ASP.NET MVC 项目中,我从来没有真正的使用过函数这个功能。我只在一个Umbraco的CMS系统中用过一次。不管怎么说,这也是扩展你视图的另一种小技巧。也许你有很复杂视图方面的业务逻辑,在这种情况下,你可以在你的视图中写C#方法:
@functions
{
public string ReverseString(string input)
{
return String.Join("", input.Reverse());
}
}
#10: 配置全局视图(Global view configuration)
最后一点,你可以在_ViewImports.cshtml
文件中,来配置你其他视图中使用的一些比较公用的 using 引用,依赖注入等。
总结
不管是以前的MVC还是新的Core MVC, 都有很多方法来扩展视图,虽然扩展这些视图的方式有些类似,但是每一种都有它最适合的地方,所以我们在使用这些特性来解决我们的问题的时候,我们应该多加思考,找到最合适的方式。
译者注:本文翻译并非逐字翻译,由于水平有限,难免出现一些错误和翻译不准确的地方,希望读者能够指出并堪正,不胜感激。
ASP.NET Core 十种方式扩展你的 Views的更多相关文章
- [转]ASP.NET Core 十种方式扩展你的 Views
http://www.cnblogs.com/savorboard/p/aspnetcore-views.html
- ASP.NET Core MVC 之局部视图(Partial Views)
1.什么是局部视图 局部视图是在其他视图中呈现的视图.通过执行局部视图生成的HTML输出呈现在调用视图中.与视图一样,局部视图使用 .cshtml 文件扩展名.当希望在不同视图之间共享网页的可重用部分 ...
- ASP.NET Core 中文文档 第三章 原理(6)全球化与本地化
原文:Globalization and localization 作者:Rick Anderson.Damien Bowden.Bart Calixto.Nadeem Afana 翻译:谢炀(Kil ...
- ASP.NET Core之跨平台的实时性能监控
前言 前面我们聊了一下一个应用程序 应该监控的8个关键位置. . 嗯..地址如下: 应用程序的8个关键性能指标以及测量方法 最后卖了个小关子,是关于如何监控ASP.NET Core的. 今天我们就来讲 ...
- ASP.NET Core 之跨平台的实时性能监控
前言 前面我们聊了一下一个应用程序 应该监控的8个关键位置. . 嗯..地址如下: 应用程序的8个关键性能指标以及测量方法 最后卖了个小关子,是关于如何监控ASP.NET Core的. 今天我们就来讲 ...
- Asp.Net Core 使用 MediatR
Asp.Net Core 使用 MediatR 项目中使用了CQRS读写分离,增删改 的地方使用了 MediatR ,将进程内消息的发送和处理进行解耦.于是便有了这篇文章,整理并记录一下自己的学习.遇 ...
- 从头编写 asp.net core 2.0 web api 基础框架 (3)
第一部分:http://www.cnblogs.com/cgzl/p/7637250.html 第二部分:http://www.cnblogs.com/cgzl/p/7640077.html 之前我介 ...
- 【转载】从头编写 asp.net core 2.0 web api 基础框架 (3)
Github源码地址:https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratc ...
- [小技巧]ASP.NET Core中如何预压缩静态文件
原文地址:Pre-compressed static files with ASP.NET Core 作者:Gunnar Peipman 译者:Lamond Lu 译文:https://www.cnb ...
随机推荐
- tp框架之验证码
控制器 function yzm() { /*$config = array( 'fontSize' => 30, // 验证码字体大小 'length' => 4, // 验证码位数 ' ...
- Android MarginEnd与MarginStart (RTL)
Android MarginLeft与MarginStart的区别http://blog.csdn.net/zhufuing/article/details/40181815 在写layout布局的时 ...
- expect命令问题1
[root@localhost scripts]# cat exptest.sh #!/usr/bin/expect spawn ssh root@127.0.0.1 expect "pas ...
- 高性能的JavaScript--数据访问(1)
写在前面 数据存储在哪里,关系到代码运行期间数据被检索到的速度.在JavaScript中,此问题相对简单,因为数据存储只有少量方式可供选择.正如其他语言那样,数据存储位置关系到访问速度.在JavaSc ...
- mysql 连接池超时
var mysql = require('mysql'); var pool = mysql.createPool({ host: 'localhost', user: 'nodejs', passw ...
- activemq 控制面板里的 Number Of Pending Messages、 Messages Enqueued、Messages Dequeued含义
Number Of Consumers 消费者 这个是消费者端的消费者数量 Number Of Pending Messages 等待消费的消息 这个是当前未出队列的数量.可以理解为总接收数-总出队 ...
- 该不该在C#中使用var关键词
作为一个并不勤快的程序猿,在项目开发过程中总是想尽办法少写代码,对var关键词的使用自然不会放过,几乎在每个能使用var的地方都用了var,对此,很多朋友同事给出了不同的建议,觉得能不使用var关键词 ...
- 2016 Multi-University Training Contest 2 D. Differencia
Differencia Time Limit: 10000/10000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...
- .NET Web开发笔记
HttpWebRequest HttpWebRequest默认关闭Cookies,给其赋初始值以打开Cookies读写 myRequest.CookieContainer = new CookieCo ...
- Holographic Remoting
看到微软官方的 Holographic Remoting Player https://developer.microsoft.com/en-us/windows/holographic/hologr ...