anytao.net | 《你必须知道的.NET》网站 | Anytao技术博客 

发布日期:2009.04.30 作者:Anytao
© 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处。

MVC时代来临了,但是一开始是不被很多人接受的。可能的主要原因是,大家不得不告别拖拉控件的至爽感受,回到貌似asp的历史岁月。所以,心有不甘是可以理解的,然而时代显然是进步的。我们虽然必须在View中进行很多HTML代码的工作,但是MVC为我们提供了可以堪称完美的方案(至少我是这样认为的),那就是HtmlHelper。在MVC的View层,我们有很多熟悉的面孔,例如Html.Encode、Html.AntiForgeryToken、Html.BeginForm、Html.TextBox等,而其中ActionLink算是其中的“猛将兄”。

浅议HtmlHelper

简单的说,HtmlHelper就是一个封装了ViewContext、IViewDataContainer、RouteCollection等上下文信息的一箩筐静态方法类(注,HtmlHelper本身并不是静态类),其中包含了我们上文介绍的熟悉身影Encode、AntiForgeryToken等,但不包含BeginForm、TextBox,当然也不包括ActionLink,其原因是BeginForm、TextBox、ActionLink其实是HtmlHelper的扩展方法,我们可以从智能感知提示中最直观的得到了解:

显然,ActionLink和Encode的智能提示标记是有区别的。

所以,HtmlHelper其实很简单,而通过Extension Methods对其的“功能注入”机制实现了极大的扩展空间。而且,HtmlHelper封装了ViewContext、RouteCollection等上下文信息,为实现扩展带来便利。所以,顺便提一下,这也正是老赵同志在为视图自定义辅助方法(上)中实现JQueryHelper时引入相应元素(ViewContext、RouteCollection、ViewPage),有着异曲同工之妙,所以HtmlHelper并不是唯一的选择,高兴的话,你也可以类似于AnytaoHelper之类的东东。

所以,通过HtmlHelper就可在运行时动态生成HTML代码,其实我们在WebForm时代就经常玩儿这种“阴招”,然而在HtmlHelper这里,显然已经发扬光大了。例如老赵的JQueryHelper就通过一系列的包装,省去了对validation的麻烦语法。

同时,扩展HtmlHelper其实及其简单。例如:

// Release : code01, 2009/04/30
// Author  : Anytao, http://www.anytao.com
public static string Label(this HtmlHelper helper, string name, string value)
{return string.Format("<label for='{0}'>{1}</label><br />", name, value);
}

通过下面的方式就可以调用该方法了:

<%= Html.Label("name", "Tao") %>
同样的道理,当我们摊开ActionLink的实现具体实现时,可见:
public static string ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, AjaxOptions ajaxOptions, IDictionary<string, object> htmlAttributes) {if (String.IsNullOrEmpty(linkText)) {throw new ArgumentException(MvcResources.Common_NullOrEmpty, "linkText");}string targetUrl = UrlHelper.GenerateUrl(null, actionName, controllerName, routeValues, ajaxHelper.RouteCollection, ajaxHelper.ViewContext.RequestContext, true /* includeImplicitMvcValues */);return GenerateLink(linkText, targetUrl, GetAjaxOptions(ajaxOptions), htmlAttributes);
}

ActionLink其实根据Action、Controller、linkText信息,通过GenerateLink生成了我们需要的HTML代码,我们将在下面继续看到影响GenerateLink的还有Route信息。

有时“胡搅蛮缠”

聊了半天HtmlHelper,该说说ActionLink了。正如前文而言,ActionLink仅仅是HtmlHelper的扩展方法而已。不过,虽然ActionLink平易近人,但是还是在不经意间发现其胡搅蛮缠的地方。我们先按下不表来看看如何使用ActionLinks,MVC Framework为我们提供了两种方式:

  • ActionLink
  • ActionLink<TController>

显而易见,一种是非泛型方法,通过参数方式调用,没有强类型优势;另一种是泛型方法,可以通过强类型调用,不过如果通过ActionName对Action进行重写标记时,泛型ActionLink<TController>是不可用的,我在《还是ActionFilter,实现对业务逻辑的统一Authorize处理》已进行过讨论了。

<%=Html.ActionLink("Edit", "Edit", "Book", new { id = Model.ID }, new { @class = "BookDetail"})%>

具体而言,上述参数主要包括:

  • Edit,为linkText,具体而言就是显示的字符串;
  • Edit,对应为ActionName;
  • Book,为Controller;
  • new { id = Model.ID },为生成元素的id定义;
  • new { @class = “BookDetail” },则为元素添加了tag要素。

具体的执行逻辑不是我们关心的问题,而上述代码生成的Source Code,则对应为:

<a class="BookDetail" href="/Book/Edit/1">Edit</a>

而如果应用泛型ActionLink,则上述调用将变成:

<%= Html.ActionLink<BookController>(c => c.Detail(), "Edit") %>

生成同样的Source Code,不过通常情况下,我们还是推荐泛型ActionLink,至少有类型安全、代码优雅的优点。

注:既然是ActionLink,文如其名,我们不能将其滥用,也就是说涉及Action的Links时可以考虑用ActionLink,其他情况下最好还是手写自己的链接代码或者扩展自己的HtmlHelper等。

然而,在有些情况下,假设我们有如下Route:

// Release : code02, 2009/04/30
// Author  : Anytao, http://www.anytao.com
routes.MapRoute("BookRoute","Tao/Book/id",new { controller = "Book", action = "Detail", id = "" });

当我们使用

<%= Html.ActionLink("Book", "Detail", "Book", null, null) %>

调用BookController下的Detail Action,不过令我们奇怪的是,生成Html代码并不如期望的那样,而是:

<a href="/Tao/Book/id">Book</a>

显然,ActionLink有点儿“胡搅蛮缠”了。其原因在于,新定义的BookRoute改写了ActionLink的“既有”行为,本来我们期望的是:

<a href="/Book/Detail/id">Book</a>

为了追查原因,我们将对ActionLink进行了必要的调查,首先了解ActionLink的定义:

public static string ActionLink(this HtmlHelper htmlHelper, string linkText, string actionName)

而ActionLink的具体实现中,我们看到了routeCollection的GetVirtualPath方法中涉及了对">">Dictionary<string, RouteBase>的操作,所以不言而喻,ActionLink生成的Url是受routeCollection影响的。对于其“胡搅蛮缠”,我相信这就是原因吧。

所以,虽是一个小小的意外,但是了解了就不是意外。对于我们的应用而言,有两点值得注意:

  • 注意Route定义对于ActionLink可能造成的影响。
  • 在这种情况下,我们可以考虑放弃ActionLink,而通过全手动方式实现:
<a href="Book/Detail/<%= Model.ID %>">Book</a>

不偿为一种回归原始的方式,不是吗?

本文调侃了题目,但是更重要的事情是我们对HtmlHelper及ActionLink有了个大致的了解,对于更好的应用是有好处的。那么,今天就说到这里。

代码下载,这里。更多关注,尽在anytao.net/blog

anytao | © 2009 Anytao.com

2009/04/30 | http://anytao.cnblogs.com/ | http://anytao.net/blog/post/2009/04/29/anytao-mvc-07-actionlinktalk.aspx

本文以“现状”提供且没有任何担保,同时也没有授予任何权利。 | This posting is provided "AS IS" with no warranties, and confers no rights.

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载于:https://www.cnblogs.com/anytao/archive/2009/04/30/anytao-mvc-04-actionlinktalk.html

[一步一步MVC]第四回:漫谈ActionLink,有时“胡搅蛮缠”相关推荐

  1. 艾伟_转载:[一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper

    本系列文章导航 [一步一步MVC]第一回:使用ActionSelector控制Action的选择 [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 [ ...

  2. [一步一步MVC]第二回:还是ActionFilter,实现对业务逻辑的统一Authorize处理 OnActionExecuting内如何获取参数...

    如何获取参数:http://www.cnblogs.com/anytao/archive/2009/04/23/anytao-mvc-02-actionauthorize.html 由问题引出 在AS ...

  3. (转) 一步一步学习ASP.NET 5 (四)- ASP.NET MVC 6四大特性

    转发:微软MVP 卢建晖 的文章,希望对大家有帮助.原文:http://blog.csdn.net/kinfey/article/details/44459625 编者语 : 昨晚写好的文章居然csd ...

  4. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](四)

    前言 上一篇<一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](三)>,我们完成了: * 引用SqlSugar * ...

  5. 设计php框架_利用 Composer 一步一步构建自己的 PHP 框架(三)——设计 MVC

    利用 Composer 一步一步构建自己的 PHP 框架(三)--设计 MVC 2014-10-14 / 阅读数:50438 / 分类: PHP 终于可以 "一次编写,到处发布" ...

  6. composer mysql_利用 Composer 一步一步构建自己的 PHP 框架(四)——使用 ORM

    利用 Composer 一步一步构建自己的 PHP 框架(四)--使用 ORM 2014-10-16 / 阅读数:65457 / 分类: PHP 回顾 经过前三篇文章 基础准备 . 构建路由 和 设计 ...

  7. 一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序 - 强烈推荐!!!

    一步一步学习ASP.NET MVC 1.0创建NerdDinner 范例程序 本文根据<Professional ASP.NET MVC 1.0>中微软牛人Scott Guthrie 提供 ...

  8. 手挽手带你学React:四档(上)一步一步学会react-redux (自己写个Redux)

    手挽手带你学React入门四档,用人话教你react-redux,理解redux架构,以及运用在react中.学完这一章,你就可以开始自己的react项目了. 之前在思否看到过某个大神的redux搭建 ...

  9. Idea 七步建立Spring Mvc 的web项目,极其简单

     Idea 7步建立Spring Mvc 的web项目   1.新建项目 新建的结构是这样的 2. 添加controller的包.文件:添加jsp的文件夹和jsp文件 文件名为HelloWorldCo ...

  10. (转)一步一步Asp.Net MVC系列_权限管理设计起始篇

    原文地址:http://www.cnblogs.com/mysweet/archive/2012/07/26/2610793.html 前一段时间,写了一步一步asp.net的一系列博客,最近,也快要 ...

最新文章

  1. java map collection_java 集合----Map、Collection
  2. 如何使用R来连接各个数据库
  3. Fiddler (三) Composer创建和发送HTTP Request
  4. python与seo应用_【张亚楠】Python在我SEO工作中的应用(1)
  5. jQuery内置动画和多库共存
  6. 昨天安装复习中遇到的问题小结
  7. tidyr | 对数据框分行或分列进行嵌套操作
  8. python map什么意思_Python中map是什么意思
  9. MFC的多国语言界面的实现
  10. phpstorm 设置注释
  11. Julia: Array的确很强大
  12. group policy client服务未能登录,拒绝访问
  13. 单片机内部弱上拉_有继电器引发对单片机驱动能力的思考!
  14. 【kaggle注册页面没有显示验证码】
  15. 算法竞赛入门【码蹄集新手村600题】(MT1101-1150)
  16. 列表求和python_python列表求和
  17. 斐讯天天链N1:分布式数据存储模式能否引领下一代数据中心变革
  18. 新版手机离线地图GPS定位程序
  19. 培养自己的核心竞争力
  20. [教程]HP Envy J/K/Q/N系列Haswell平台 Clover引导安装黑苹果

热门文章

  1. 厦门理工学院OJ题解(1223:Rite与跳舞毯)
  2. uniapp小程序src引用服务器图片时全局变量与图片路径拼接
  3. 三维地理信息系统空间的可视分析
  4. 解析 embedded.mobileprovision 获取信息
  5. python 强大的错误重试库 tenacity retry
  6. Eclipse中各种查找快捷键
  7. 横版过关游戏开发-游戏流程
  8. 修真院教学模式三大阶段之任务体系
  9. 【网络安全】如何使用OpenSSL工具生成根证书与应用证书
  10. SLAM之回环检测与优化