原文地址:/stephenwalther/archive//06/13/asp-net-mvc-tip-1-creating-new-html-helpers-with-extension-methods.aspx
摘要:在这个Tip中,Stephen Walther创建了两个新的HTML Helper,你可以直接在 MVC视图中使用它们。Stephen Walther展示了如何用扩展方法创建用于显示无序列表和有序列表的HTML Helper。
在为 MVC应用程序创建视图时,你可以使用HTML Helper来呈现标准的HTML标签。例如,对于下面的代码:
<inputname="inpSubmit"type="submit"value="ClickHere!"/>
可以写为:
<%=Html.SubmitButton("inpSubmit","ClickHere!")%>
后面这种写法可以为你节省大量的时间。但如果没有与你要呈现的标签对应的HTML Helper呢?例如,假设你要在视图中为数据库记录显示一个无序列表。HtmlHelper类中并未包含用于显示无序列表的方法。别灰心,如果HTML Helper中没有你需要的方法,尽管去扩展它吧!
通过建立新的扩展方法,你可以向HtmlHelper类添加新的功能。扩展方法看上去和普通的实例方法类似。然而,与实例方法不同,你可以在完全不同的类中为另外一个类添加扩展方法。
在Visual Basic .NET中,创建扩展方法的方法是创建一个模块,并用一个特殊的特性来声明一个方法。在C#中,可以在一个静态类中定义扩展方法,并使用关键字this来指出要扩展的类。
下面展示了如何为HtmlHelper类添加扩展方法来为数据库记录显示有序列表和无序列表:
清单1 - ListExtensions.vb ()
1ImportsSystem
2ImportsSystem.Collections
3ImportsSystem.Text
4ImportsSystem.Web
5ImportsSystem.Web.Mvc
pilerServices
7
8NamespaceHtmlHelpersNamespaceHtmlHelpers
9PublicModuleListExtensionsModuleListExtensions
10<Extension()>_
11PublicFunctionOrderedList()FunctionOrderedList(ByValHtmlHelperAsHtmlHelper,ByValitemsAsObject)AsString
12Return"<ol>"+ListExtensions.GetListItems(items)+"</ol>"
13EndFunction
14
15<Extension()>_
16PublicFunctionUnorderedList()FunctionUnorderedList(ByValHtmlHelperAsHtmlHelper,ByValitemsAsObject)AsString
17Return"<ul>"+ListExtensions.GetListItems(items)+"</ul>"
18EndFunction
19
20PrivateFunctionGetListItems()FunctionGetListItems(ByValitemsAsObject)AsString
21IfitemsIsNothingThen
22ThrowNewArgumentNullException("items")
23EndIf
24IfNotTypeOfitemsIsIEnumerableThen
25ThrowNewInvalidCastException("itemsmustbeIEnumerable")
26EndIf
27
28DimEnumItemsAsIEnumerable=CType(items,IEnumerable)
29DimbuilderAsNewStringBuilder()
30
31ForEachitemAsObjectInEnumItems
32builder.AppendFormat("<li>{0}</li>",HttpUtility.HtmlEncode(item.ToString()))
33Next
34
35Returnbuilder.ToString()
36EndFunction
37EndModule
38EndNamespace
清单1 - ListExtensions.cs (C#)
usingSystem;
usingSystem.Collections;
usingSystem.Text;
usingSystem.Web;
usingSystem.Web.Mvc;
namespaceBulletedListHelper.HtmlHelpers
{
publicstaticclassListExtensions
{
publicstaticstringOrderedList(thisHtmlHelperhelper,Objectitems)
{
return"<ol>"+ListExtensions.GetListItems(items)+"</ol>";
}
publicstaticstringUnorderedList(thisHtmlHelperhelper,Objectitems)
{
return"<ul>"+ListExtensions.GetListItems(items)+"</ul>";
}
privatestaticstringGetListItems(Objectitems)
{
if(items==null)
thrownewArgumentNullException("items");
if(itemsisIEnumerable==false)
thrownewInvalidCastException("itemsmustbeIEnumerable");
varenumItems=(IEnumerable)items;
varbuilder=newStringBuilder();
foreach(ObjectiteminenumItems)
builder.AppendFormat("<li>{0}</li>",HttpUtility.HtmlEncode(item.ToString()));
returnbuilder.ToString();
}
}
}
ListExtensions类有两个公共方法——OrderedList()和UnorderedList()。将集合分别传入两个方法,可以分别显示有序和无序列表。注意这些方法返回的是字符串。的确,HTML Helper方法的作用就是向浏览器呈现一个格式化的字符串。
创建完扩展方法后,你可以在视图中像下面这样使用它:
清单2 - Index.aspx
<%@PageLanguage="VB"MasterPageFile="~/Views/Shared/Site.Master"AutoEventWireup="false"CodeBehind="Index.aspx.vb"Inherits="BulletedListHelper.Index"%>
<%@ImportNamespace="BulletedListHelper.HtmlHelpers"%>
<asp:ContentID="indexContent"ContentPlaceHolderID="MainContent"runat="server">
<h1>Movies(Ordered)</h1>
<%=Html.OrderedList(ViewData.Model)%>
<h1>Movies(Unordered)</h1>
<%=Html.UnorderedList(ViewData.Model)%>
</asp:Content>
注意在文件的顶部引入了BulletedList.HtmlHelpers命名空间。Html.OrderedList()用于呈现有序列表,而Html.UnorderedList()用于呈现无序列表。注意在View的Html属性所暴露的HtmlHelper对象上调用了这些方法,和其他扩展方法一样。当你在浏览器中打开该视图时,可以得到如图1所示的页面:
图1 - 使用自定义HTML Helper呈现的Index.aspx
最后清单3给出了HomeController所暴露的Index()方法,该方法展示了如何将一个电影记录集合传递给Index.aspx视图。电影记录是利用Linq to SQL查询得到的。
清单3 - HomeController.vb ()
PublicClassHomeControllerClassHomeController
InheritsSystem.Web.Mvc.Controller
PrivatedbAsNewMoviesDataContext()
FunctionIndex()FunctionIndex()
Dimmovies=FrommIndb.MoviesSelectm.Title
ReturnView(movies)
EndFunction
EndClass
清单3 - HomeController.cs (C#)
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Mvc;
usingBulletedListHelper.Models;
namespaceBulletedListHelper.Controllers
{
publicclassHomeController:Controller
{
privateMoviesDataContextdb=newMoviesDataContext();
publicActionResultIndex()
{
varmovies=frommindb.Moviesselectm.Title;
returnView(movies);
}
}
}
你可以使用这种方式向 MVC视图中呈现几乎任何东西。例如,你可以使用类似的方法创建TreeView、Menu、TabStrip等等。
此处下载源代码:/blogs/stephenwalther/Downloads/Tip1/ListHtmlHelpers.zip