ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法
一、一个功能强大的页面开发辅助类—HtmlHelper初步了解
1.1 有失必有得

在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归。所以抛弃之前的那种事件响应的模型,抛弃服务器端控件也理所当然。
但是,如果手写Html标签效率又比较低,可重用度比较低。这时,我们该怎样来提高效率呢?首先,经过上篇我们知道可以通过ViewData传递数据,于是我们可以写出以下的Html代码:
|
1
|
<input name="UserName" type="text" value="<%: ViewData["UserName"] %>" /> |
虽然以上代码可以解决问题,但是效率还是比较低,特别是在列表集合项较多的时候,工作量会比较大。那么,还有木有一种更好的方式呢?别急,微软已经为我们想好了策略。微软为开发人员快速开发前台页面提供了丰富的HtmlHelper的辅助类,辅助我们快速开发前台页面,也提供了可扩展的接口,前台页面的标签可以可以做到高度可重用。
1.2 HtmlHelper初窥
我们可以通过在页面中通过Html.XXX来实现快速的Html标签编辑,并且可以方便地进行数据绑定。
|
1
|
<%: Html.Raw("<p>Hello,I am HtmlHelper!</p>") %> |
那么,为什么可以在页面中调用Html.XXX方法呢?通过ILSpy反编译ViewPage页,我们可以看到原来在ViewPage下有一个HtmlHelper类型的属性-Html。(这下终于知道,为什么可以在页面中使用Html.xxxx()了)

那么这个HtmlHelper类又是一个什么类型的大神呢?继续反编译查看,在System.Web.Mvc命名空间下的HtmlHelper类型 如下图所示,经过MSDN大神的讲解,HtmlHelper支持在视图中呈现 HTML 控件。那我们看看在此类中有木有传说中的TextBox、CheckBox的方法呢?经查看,木有。

那么,我们为什么可以在页面中使用Html.TextBox()方法呢?这里就涉及到一个叫做“扩展方法”的东东了,HtmlHelper 类的扩展方法在System.Web.Mvc.Html 命名空间中。 这些扩展添加了用于创建窗体、呈现 HTML 控件、呈现分部视图、执行输入验证等功能的帮助器方法。那么,有关如何自定义扩展方法请参阅本文第三部分,这里先卖个关子,暂不介绍。

1.3 为什么使用HtmlHelper?
思考这样一个场景:我们的项目第一个版本中的路由规则是这样的{controller}/{action}/{id},于是我们项目中所有 的<a>标签所指向的都是以刚刚的规则命名的href(例如:<a href=’Home/User/1′></a>)。但是在第二版中,我们的路由规则也会变成了{controller}- {action}-{id},那么我们刚刚为超链接所设置的href便都无法正常访问了。这时,我们需要进行替换,单个替换或批量替换(例如改 为:<a href=’Home-User-1′></a>),虽然也可以解决问题,但是无疑增加了工作量,效率很低。
那么,怎样来屏蔽这种变化所带来的不便呢?这里,通过使用HtmlHelper为我们提供的ActionLink标签,便可以解决这个问题。因为 HtmlHelper是从服务器端自动帮你生成a标签,因此所生成的href会遵循目前的路由规则,也就帮我们屏蔽了变化,提高了工作效率。
二、没有服务器控件也能干大事—HtmlHelper重要方法介绍
PS:这里的实例均没有加<% %>或@符号,要运行请自行加上。
(1)ActionLink与RouteLink
|
1
2
3
4
5
6
7
8
9
10
|
Html.ActionLink("这是一个连接", "Index", "Home")带有QueryString的写法Html.ActionLink("这是一个连接", "Index", "Home", new { page=1 },null)Html.ActionLink("这是一个连接", "Index", new { page=1 })有其它Html属性的写法Html.ActionLink("这是一个连接", "Index", "Home", new { id="link1" })Html.ActionLink("这是一个连接", "Index",null, new { id="link1" })QueryString与Html属性同时存在Html.ActionLink("这是一个连接", "Index", "Home", new { page = 1 }, new { id = "link1" })Html.ActionLink("这是一个连接", "Index" , new { page = 1 }, new { id = "link1" }) |
其生成的结果为:
|
1
2
3
4
5
6
7
8
9
10
|
<a href="/">这是一个连接</a>带有QueryString的写法<a href="/?page=1">这是一个连接</a><a href="/?page=1">这是一个连接</a>有其它Html属性的写法<a href="/?Length=4" id="link1">这是一个连接</a><a href="/" id="link1">这是一个连接</a>QueryString与Html属性同时存在<a href="/?page=1" id="link1">这是一个连接</a><a href="/?page=1" id="link1">这是一个连接</a> |
RouteLink在用法几乎与ActionLink一致,这里就不再介绍,详情请参与MSDN;
(2)TextBox与TextArea
①TextBox
|
1
2
3
4
|
Html.TextBox("input1") Html.TextBox("input2",Model.CategoryName,new{ @style = "width:300px;" }) Html.TextBox("input3", ViewData["Name"],new{ @style = "width:300px;" }) Html.TextBoxFor(a => a.CategoryName, new { @style = "width:300px;" }) |
其生成的结果为:
|
1
2
3
4
|
<input id="input1" name="input1" type="text" value="" /><input id="input2" name="input2" style="width:300px;" type="text" value="Beverages" /><input id="input3" name="input3" style="width:300px;" type="text" value="" /><input id="CategoryName" name="CategoryName" style="width:300px;" type="text" value="Electronic" /> |
②TextArea
|
1
2
|
Html.TextArea("input5", Model.CategoryName, 3, 9,null)Html.TextAreaFor(a => a.CategoryName, 3, 3, null) |
其生成的结果为:
|
1
2
|
<textarea cols="9" id="input5" name="input5" rows="3">Electronic</textarea><textarea cols="3" id="CategoryName" name="CategoryName" rows="3">Electronic</textarea> |
这里可以看到,我们可以使用强类型来生成Html标签,例如:Html.TextBoxFor(a => a.CategoryName, new { @style = “width:300px;” }),这里的CategoryName就是某个类型的属性。
(3)CheckBox
|
1
2
3
|
Html.CheckBox("chk1",true) Html.CheckBox("chk1", new { @class="checkBox"}) Html.CheckBoxFor(a =>a.IsVaild, new { @class = "checkBox" }) |
其生成的结果为:
|
1
2
3
|
<input checked="checked" id="chk1" name="chk1" type="checkbox" value="true" /><input name="chk1" type="hidden" value="false" /><input class="checkBox" id="chk1" name="chk1" type="checkbox" value="true" /><input name="chk1" type="hidden" value="false" /><input checked="checked" class="checkBox" id="IsVaild" name="IsVaild" type="checkbox" value="true" /><input name="IsVaild" type="hidden" value="false" /> |
(4)DropDownList
|
1
2
|
Html.DropDownList("ddl1", (SelectList)ViewData["Categories"], "--Select One--")Html.DropDownListFor(a => a.CategoryName, (SelectList)ViewData["Categories"], "--Select One--", new { @class = "dropdownlist" }) |
其生成的结果为:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<select id="ddl1" name="ddl1"><option value="">--Select One--</option><option value="1">Beverages</option><option value="2">Condiments</option><option selected="selected" value="3">Confections</option><option value="4">Dairy Products</option><option value="5">Grains/Cereals</option><option value="6">Meat/Poultry</option><option value="7">Produce</option><option value="8">Seafood</option></select><select class="dropdownlist" id="CategoryName" name="CategoryName"><option value="">--Select One--</option><option value="1">Beverages</option><option value="2">Condiments</option><option value="3">Confections</option><option value="4">Dairy Products</option><option value="5">Grains/Cereals</option><option value="6">Meat/Poultry</option><option value="7">Produce</option><option value="8">Seafood</option></select> |
(5)RadioButton
|
1
2
|
男<%: Html.RadioButton("Gender","1",true) %>女<%: Html.RadioButton("Gender","2",false) %> |
其生成的代码为:
|
1
2
|
男<input checked="checked" id="Gender" name="Gender" type="radio" value="1" />女<input id="Gender" name="Gender" type="radio" value="2" /> |
(6)Encode与Raw
Encode会将内容进行编码话,因此,如果你的内容中含有Html标签的话那么会被解析成特殊字符,例如:
|
1
|
<%: Html.Encode("<p>哈哈</p>") %> |
其生成的代码为:
|
1
|
&lt;p&gt;哈哈&lt;/p&gt; |
这里主要是为了防止XSS攻击和恶意脚本,因此在MVC中,默认的<%: %>就实现了<%: Html.Encode() %>。但是,某些时候如果我们需要输出Html或JavaScript内容的字符串,这时我们可以使用HtmlHelper为我们提供的其他方法。 例如我们要输出刚刚那句话,我们可以如下使用:
|
1
|
<%: Html.Raw("<p>哈哈</p>") %> |
其生成的代码为:
|
1
|
<p>哈哈</p> |
在HtmlHelper中还提供了许多的扩展方法供我们方便创建Html,比如:BeginForm、EndForm等。关于其他的方法介绍,请自行搜索,这里不再一一赘述。
三、随时随地我也能扩展—HtmlHelper扩展方法简介
3.1 扩展方法简介
借助MSDN的介绍:“扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。”扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用。我们可以回到第一部分对HtmlHelper的扩展类-InputExtension类上,它是对于HtmlHelper的扩展,那么怎么鉴别它是HtmlHelper的扩展呢?
3.2 扩展方法的三要素

(1)静态类
可以从上图看出,InputExtension首先是一个静态类;
(2)静态方法
既然是静态类,那么其所有的方法必然都是静态方法,例如:public static MvcHtmlString CheckBox();
(3)this关键字
可以从方法名定义中看出,第一个参数都是this HtmlHelper htmlHelper,代表对HtmlHelper类的扩展;
3.3 自定义扩展方法
(1)在Models文件夹下新建一个类,取名为:MyHtmlHelperExt
(2)将MyHtmlHelperExt设置为static,并写入以下的一个静态方法:
|
1
2
3
4
|
public static HtmlString MyExtHtmlLabel(this HtmlHelper helper, string value){ return new HtmlString(string.Format("<span style='font-weight:bold;'>Hello-{0}-End</span>", value));} |
(3)确定满足了扩展方法的三要素之后,将命名空间改为:System.Web.Mvc。
|
1
|
namespace System.Web.Mvc |
PS:为什么要改命名空间为System.Web.Mvc?
这是因为如果不改命名空间,我们要使用自定义的扩展方法需要在每个页面中引入Models(MyHtmlHelper所在的那个命名空间)这个命名 空间,为了防止重复的命名空间引入操作(想想我们使用Html.TextBox()不也没有引入命名空间么?),于是我们将命名空间与 HtmlHelper类所在的命名空间保持一致。
(4)在页面中我们就可以使用我们自己写的扩展方法了
|
1
|
<%: Html.MyExtHtmlLabel("EdisonChou") %> |
(5)查看页面效果

参考文章
(1)马伦,《ASP.Net MVC视频教程》,http://bbs.itcast.cn/thread-26722-1-1.html
(2)oer,《HtmlHelper使用大全》,http://www.cnblogs.com/oer2001/archive/2013/03/19/2968475.html
(3)MSDN,《扩展方法(C#编程指南)》,http://technet.microsoft.com/zh-cn/bb383977
(4)MSDN,《HtmlHelper类(System.Web.Mvc)》,http://msdn.microsoft.com/zh-cn/library/system.web.mvc.htmlhelper(v=vs.108).aspx
ASP.Net MVC开发基础学习笔记(2):HtmlHelper与扩展方法的更多相关文章
- ASP.Net MVC开发基础学习笔记:一、走向MVC模式
一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/bl ...
- ASP.Net MVC开发基础学习笔记(1):走向MVC模式
一.ASP.Net的两种开发模式 1.1 ASP.Net WebForm的开发模式 (1)处理流程 在传统的WebForm模式下,我们请求一个例如http://www.aspnetmvc.com/bl ...
- ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法
一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归. ...
- ASP.Net MVC开发基础学习笔记:三、Razor视图引擎、控制器与路由机制学习
一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留 ...
- ASP.Net MVC开发基础学习笔记:四、校验、AJAX与过滤器
一.校验 — 表单不是你想提想提就能提 1.1 DataAnnotations(数据注解) 位于 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据 ...
- ASP.Net MVC开发基础学习笔记:五、区域、模板页与WebAPI初步
一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新 ...
- ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步
一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新 ...
- ASP.Net MVC开发基础学习笔记(4):校验、AJAX与过滤器
一.校验 — 表单不是你想提想提就能提 1.1 DataAnnotations(数据注解) 位于 System.ComponentModel.DataAnnotations 命名空间中的特性指定对数据 ...
- ASP.Net MVC开发基础学习笔记(3):Razor视图引擎、控制器与路由机制学习
一.天降神器“剃须刀” — Razor视图引擎 1.1 千呼万唤始出来的MVC3.0 在MVC3.0版本的时候,微软终于引入了第二种模板引擎:Razor.在这之前,我们一直在使用WebForm时代沿留 ...
随机推荐
- gridview 实现鼠标悬浮行提示行中列的信息
protected void GridView1_RowDataBound(object sender, GridViewRowEventArgs e) { for (int i = ...
- linux查看系统版本和系统位数
1. uname -a you will view kernel name.network node hostname.kernel release.kernel version.machine h ...
- 通过JavaScript操作HTML中select标签
添加: Js代码 1.function selectChange() 2.{ 3.var sel=document.getElementById("select1"); 4. Op ...
- OKhttp的封装(上)
自从介绍了OKhttp3的一些基本使用之后,又偷了下懒,所以它的续篇被搁置了一段时间,现在补充. OKhttpManager.Class 请求工具类 package com.example.admi ...
- 在没装VS2010的机器上运行VS2010开发的C++程序
在VS2010下写了一个win32控制台应用程序,编译ok.exe,需要依赖osg相关动态库 第一次编译的是Debug版本的,直接将ok.exe和osg相关dll文件拷贝到没有安装VS2010机器上运 ...
- 大数计算_BigNum优化_加减乘除乘方取余_带注释_数组
#include <iostream> #include <algorithm> #include <cstring> #include <cstdlib&g ...
- UbuntuLinux安装java
jdk1.7,jdk1.8详情,参见:http://www.cnblogs.com/a2211009/p/4265225.html
- Maven中手动引用第三方jar包
有些jar包在Maven库中并不支持,但我们又需要.所以就必须手动引入. 可分为三步完成: 1 ,在项目目录下创建Lib,把引入的jar包加入. 2.在pom.xml中引入dependences. 如 ...
- C --gettimeofday===获取某个程序经历的时间
#include <stdio.h> #include <sys/time.h> #include <time.h> int gettimeofday(struct ...
- 学习SQLAlchemy Core
有时间了就要慢慢看,死守DJANGO ORM,明显没有SQLAlchemy有优势. 因为SQLAlchemy针对整个PYTHON都是有用的. 找了本书,慢慢撸. <Essential.SQLAl ...