精通ASP.NET MVC ——辅助器方法
輔助器方法(Helper Method),其作用是對代碼塊和標(biāo)記進(jìn)行打包,以便能夠在整個MVC框架應(yīng)用程序中重用。
首先新建一個項目,添加一個Home控制器,如下圖所示:
public class HomeController : Controller{// GET: Homepublic ActionResult Index(){ViewBag.Fruits = new string[] { "Apple", "Orange", "Pear" };ViewBag.Cities = new string[] { "New York","London","Paris"};string message = "This is an HTML element:<input>";return View((object)message);}}對應(yīng)的視圖Index.cshtml頁面,代碼如下圖所示:?
@{Layout = null; }<!DOCTYPE html><html> <head><meta name="viewport" content="width=device-width" /><title>Index</title> </head> <body><div> Here are the fruites:@foreach (string str in (string [])ViewBag.Fruits){<b>@str</b>}</div><div>Here are the cities:@foreach (string str in (string [])ViewBag.Cities){<b>@str</b>}</div><div>Here is the message:<p>@Model</p></div> </body> </html>運(yùn)行效果如下圖所示:?
? ? ? ? ? ??
創(chuàng)建內(nèi)聯(lián)的自定義輔助器方法
修改Index.cshtml頁面,代碼如下圖所示:
@{Layout = null; }@helper ListArrayItems(string [] items) { foreach (string str in items){<b>@str</b>} }<!DOCTYPE html> <html> <head><meta name="viewport" content="width=device-width" /><title>Index</title> </head> <body><div> Here are the fruites:@ListArrayItems(ViewBag.Fruits)</div><div>Here are the cities:@ListArrayItems(ViewBag.Cities)</div><div>Here is the message:<p>@Model</p></div> </body> </html>在上述代碼中,定義了一個名稱為ListArrayItems的輔助器,它以一個字符串?dāng)?shù)組為參數(shù)。?雖然內(nèi)聯(lián)輔助器看上去像一個方法。但是它沒有返回值。這種辦法的好處是,如果希望改變數(shù)組內(nèi)容顯示的方式,只需要一處修改,如下圖所示:
@helper ListArrayItems(string [] items) {<ul>@foreach (string str in items){<li>@str</li>}</ul> }運(yùn)行效果如下圖所示:?
? ? ? ? ? ? ? ? ? ? ? ? ? ?
創(chuàng)建外部輔助器方法?
內(nèi)聯(lián)輔助器是方便的,但是只能在聲明它們的視圖之中使用,而且,如果內(nèi)聯(lián)輔助器太復(fù)雜,可能會占據(jù)視圖,影響閱讀。這時就可以用到外部輔助器方法。在項目中添加一個Infrastructure文件夾,并創(chuàng)建一個新的類文件CustomHelp.cs,如下圖所示:
public static class CustomerHelpers{public static MvcHtmlString ListArrayItems(this HtmlHelper html,string[] list){TagBuilder tag = new TagBuilder("ul");foreach (string str in list){TagBuilder itemTag = new TagBuilder("li");itemTag.SetInnerText(str);tag.InnerHtml += itemTag.ToString();}return new MvcHtmlString(tag.ToString());}}?輔助器方法的第一個參數(shù)是HtmlHelper對象,它以this關(guān)鍵字為前綴,告訴C#編譯器,這是一個擴(kuò)展方法。HtmlHelper能夠在創(chuàng)建內(nèi)容時,對有用信息進(jìn)行訪問,如下圖所示:
| 屬性 | 描述 |
| RouteCollection | 返回應(yīng)用程序定義的路由集合 |
| ViewBag | 返回視圖包數(shù)據(jù),這些數(shù)據(jù)是從動作方法傳遞給調(diào)用輔助器方法的視圖的 |
| ViewContext | 返回ViewContext對象,該對象能夠?qū)φ埱蟮募?xì)節(jié)以及請求的處理方式進(jìn)行訪問 |
| 屬性 | 描述 |
| Controller | 返回處理當(dāng)前請求的控制器 |
| HttpContext | 返回描述當(dāng)前請求的HttpContext對象 |
| IsChildAction | 如果已調(diào)用輔助器的視圖正由一個子動作渲染,則返回true |
| RouteData | 返回請求的路由數(shù)據(jù) |
| View | 返回調(diào)用輔助器方法的IView實現(xiàn)的實例 |
?創(chuàng)建HTML最容易的方式是使用TagBuilder類,它能夠建立HTML字符串,而不需要處理轉(zhuǎn)義及特殊字符串。
| 成員 | 描述 |
| InnerHtml | 這是一個以HTML字符串來設(shè)置元素內(nèi)容的屬性。賦給這個屬性的值將不進(jìn)行編碼,意即可以將它嵌入HTML元素。 |
| SetInnerText(string) | 設(shè)置HTML元素的文本內(nèi)容。string參數(shù)將被編碼,以使它安全顯示。 |
| AddCssClass(string) | 對HTML元素添加一個CSS的class |
| MergeAttribute(string,string,bool) | 對HTML元素添加一個屬性,第一個參數(shù)是屬性名稱,第二是它的值,bool參數(shù)指定是否替換已存在的同名屬性。 |
使用自定義的外部輔助器方法?
@model string @using WebApplication1.Infrastructure @{Layout = null; }<!DOCTYPE html> <html> <head><meta name="viewport" content="width=device-width" /><title>Index</title> </head> <body><div> Here are the fruites:@Html.ListArrayItems((string [])ViewBag.Fruits)</div><div>Here are the cities:@Html.ListArrayItems((string[])ViewBag.Cities)</div><div>Here is the message:<p>@Model</p></div> </body> </html>運(yùn)行效果還是一樣:
? ? ? ? ? ? ? ? ? ? ? ? ???
?
輔助器方法中的字符串編碼?
MVC框架會保護(hù)你免收惡意數(shù)據(jù)的攻擊,這是通過對數(shù)據(jù)進(jìn)行自動編碼實現(xiàn)的。
如Controller中代碼是這樣的:
? ? ? ? ? ? ? ??
View的顯示結(jié)果是這樣的:?
? ? ? ? ? ? ? ? ??
而MVC框架會認(rèn)為輔助器方法生成內(nèi)容是安全的。輔助器方法會在瀏覽器端顯示input元素,而這個這可能會被利用以破壞程序的行為。在CustomerHelpers定義一個新的輔助方法看看這一情況:
public static MvcHtmlString DisplayMessage(this HtmlHelper html, string msg){string result = string.Format("This is the message:<p>{0}</p>",msg);return new MvcHtmlString(result);}修改Index.cshtml頁面如下所示:
@model string @using WebApplication1.Infrastructure @{Layout = null; }<!DOCTYPE html> <html> <head><meta name="viewport" content="width=device-width" /><title>Index</title> </head> <body><div> Here are the fruites:@Html.ListArrayItems((string [])ViewBag.Fruits)</div><div>Here are the cities:@Html.ListArrayItems((string[])ViewBag.Cities)</div><p> This is content from the view</p><div style="border:thin solid black; padding:10px"></div><div>Here is the message:<p>@Model</p></div><p> This is content from the helper method</p><div style="border:thin solid black; padding:10px"></div><div>Here is the message:<p>@Html.DisplayMessage(Model)</p></div></body> </html>運(yùn)行效果如下圖所示:
? ? ? ? ? ? ??
?對輔助器方法的內(nèi)容進(jìn)行編碼
有兩種方式:第一種最簡單的解決辦法是將輔助器方法的返回值類型改為string。但是這種方式在需要生成HTML元素時可能會有問題,不需要生成HTML元素時會比較簡單,如下圖所示:
public static string DisplayMessage(this HtmlHelper html, string msg){string result = string.Format("This is the message:<p>{0}</p>", msg);return result;}運(yùn)行情況如下圖所示,對p元素也進(jìn)行了編碼:?
? ? ? ? ??
第二種方式是用HtmlHelp類中定義的Encode方法?,選擇性的對數(shù)據(jù)進(jìn)行編碼,代碼如下圖所示:
public static MvcHtmlString DisplayMessage(this HtmlHelper html, string msg){string encodedMessage = html.Encode(msg);string result = string.Format("This is the message:<p>{0}</p>", encodedMessage);return new MvcHtmlString(result);}運(yùn)行情況如下圖所示:?
? ? ? ? ? ?
?使用內(nèi)建的Form輔助器方法
| 重載 | 描述 |
| BeginForm() | 創(chuàng)建一個表單,回遞給源動作方法(源動作方法指引發(fā)渲染該表單的動作方法) |
| BeginForm(action,controller) | 創(chuàng)建一個表達(dá),回遞給以字符串形式指定的動作方法和控制器 |
| BeginForm(action,controller,method) | 上一個方法的重載版本,但可以用System.Web.Mvc.FormMethod枚舉一個值,來指定form元素中的method標(biāo)簽屬性的值 |
| BeginForm(action,controller,method,attributes) | 上一個方法的重載版本,但能夠為form元素的標(biāo)簽屬性指定一個對象,該對象的屬性作為標(biāo)簽屬性的名稱 |
| BeginFom(action,controller,routeValues,method,attributtes) | 上一個方法的重載版本,但能夠為應(yīng)用程序路由配置中的路由片段變量指定一個值,這個值作為一個對象,該對象的屬性對應(yīng)于路由變量。 |
例如,舉例一個最復(fù)雜的重載:?
@using (Html.BeginForm( "CreatePerson", //動作方法名稱 "Home", //控制器名稱 new { id = "MyIdValue"}, //路由配置中id片段變量的值 FormMethod.Post, //form元素中method標(biāo)簽屬性的值 new { @class = "personClass",data_formType = "person"} // form元素的其他標(biāo)簽屬性 ))指定表單使用的路由?
當(dāng)使用BeginForm方法時,MVC框架會在能夠用來生成指定動作和控制器目標(biāo)的URL的路由配置中找出一條路由。從本質(zhì)上說,這是讓MVC框架去判斷進(jìn)行的路由選擇。如果你希望確保使用一條路由,那么可以替換成BeginRouteForm方法。
假設(shè)新增如下路由:
routes.MapRoute(name:"FormRoute",url:"app/forms/{controller}{action}" );?BeginRouteForm使用方法如下:
@using(Html.BeginRouteForm( "FormRoute", //路由名稱 new {}, //用于路由片段變量 FormMethod.Post, //用于form的method標(biāo)簽屬性 new { @class = "personClass",data_formType = "person"}//用于form的其他標(biāo)簽屬性 ))?使用輸入輔助器
| HTML元素 | 示例 |
| Check box (檢查框或復(fù)選框) | Html.CheckBoxFor(x => x.IsApproved) output: <input id = "IsApproved" name = "IsApproved" type = "checkbox" value = "true"/> <input name = "IsApproved" type = "hidden" value = "false"/> |
| Hidden field (隱藏字段) | Html.HiddenFor(x => x.FirstName) output: <input id = "FirstName" name = "FirstName" type = "hidden" value = ""/> |
| Radio button (無線按鈕或單選按鈕) | Html.RadioButtonFor(x => x.IsApproved,"val") output: <input id = "IsApproved" name = "IsApproved" type = "radio" value = "val"/> |
| Password (口令字段) | Html.PasswordFor(x => x.Password) output: <input id = "Password" name = "Password" type = "password"/> |
| Text area (文本區(qū)) | Html.TextAreaFor(x => x.Bio,5,20,new{}) output: <textarea cols = "20" id = "Bio" name = "Bio" rows = "5">Bio value</textarea> |
| Text box (文本框) | Html.TextBoxFor( x => x.FirstName) output: <input id = "FirstName" name = "FirstName" type = "text" value = ""/> |
使用Select元素?
| HTML元素 | 示例 |
| Drop-down list (下拉列表) | Html.DropDownList("myList", new SelectList(new [] { "A" ,"B"}), "Choose") output: <select id = "myList" name = "myList"> <option value = ""> choose</option> <option> A </option> <option> B</option> </select> |
| Drop-down list (下拉列表) | Html.DropDownListFor( x => x.Gender,?new SelectList(new [] { "M" ,"F"}), "Choose") output: <select id = "Gender" name = "Gender"> <option value = ""> choose</option> <option> A </option> <option> B</option> </select> |
| Mutiple-select (多項選擇) | Html.ListBox( "myList",?new MultiSelectList(new [] { "A" ,"B"})) output: <select id = "myList" multiple = "multiple ",name = "myList"> <option value = ""> choose</option> <option> A </option> <option> B</option> </select> |
| Mutiple-select (多項選擇) | Html.ListBoxFor(? x => Vals,?new MultiSelectList(new [] { "A" ,"B"})) output: <select id = "Vals" multiple = "multiple ",name = "Vals"> <option value = ""> choose</option> <option> A </option> <option> B</option> </select> |
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的精通ASP.NET MVC ——辅助器方法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php里面的 n算是,用PHP中的bcm
- 下一篇: [深入学习C#]匿名函数、委托和Lamb