上述這些方法如果想要增加多個HTML屬性,自然就要在方法內新增參數,有不同的多載方法可以供我們來使用。
例如下面的HTML程式碼:
<input type="text" name="id" class="form-control" required />
用HTML Helper來呈現就會變成:
@Html.TextBox("id", null, new { @class = "form-control", @required = "required" })
看起來不是很好懂,用下面的範例來說明吧~
● 範例-登入流程
之前的專案已經寫了很多內容有點雜了,這邊新開一個專案,專案名稱就叫HTMLHelperDemo吧~然後選擇MVC的架構建立。
我們今天一樣來寫個登入操作畫面,範例的重點放在如何用HTML Helper改寫原本HTML語法的View頁面,所以先照下面步驟完成。
新增名為HelperController
的控制器,建立後Code如下:
public class HelperController : Controller
// GET: Helper
public ActionResult Index()
return View();
新增 Index()
方法的View,一樣照預設套用版面配置頁就好
在View添加下列HTML程式碼,使用form表單將要提交的內容包住,form提交指定的路徑是~/Helper/Login
,並使用POST請求:
ViewBag.Title = "Index";
<h2>Index</h2>
<div class="container">
<form action="~/Helper/Login" method="post">
<label>帳號:</label>
<input type="text" name="id" class="form-control" required />
<label>密碼:</label>
<input type="password" name="password" class="form-control" required />
<input type="submit" name="submit" value="登入" class="btn btn-primary" />
</form>
補充說明一下,帳號和密碼的欄位都有一個required
的屬性,這代表在登入時會先驗證欄位是否有輸入,執行畫面如下:
新增名為Login
的動作方法,且會帶入帳號和密碼的兩個參數id
& password
,還記得參數名稱是對應HTML標籤內的name
屬性嗎?另外這裡使用ViewBag攜帶參數到登入後的View。
[HttpPost]
public ActionResult Login(string id ,string password)
ViewBag.id = id;
ViewBag.password = password;
return View();
新增Login
方法的View,這裡簡單顯示登入的帳號密碼資料就好,另外增加一個可以回登入畫面的連結,Code如下:
ViewBag.Title = "Login";
<h2>Login</h2>
<div class="container">
<li>帳號: @ViewBag.id</li>
<li>密碼: @ViewBag.password</li>
<a href="~/Helper/Index" name="link" class="btn btn-sm btn-default">回登入畫面</a>
到這邊都算是前幾天的教學內容,可以先執行操作看看是否能正常輸入帳密,登入後能顯示資料的畫面,按下回登入畫面連結也能回到登入畫面。如果有問題先檢視前面步驟有沒有錯誤。
● 使用HTML Helper 改寫畫面
接著我們來將原本View的程式碼改用HTML Helper呈現,先看到Index的View,可以改寫的部分是<form>
、<label>
、<input>
標籤,另外在Login的View可以改寫<a>
標籤。
<label>
標籤這邊沒有加任何屬性所以最簡單,改寫對照如下:
<label>帳號:</label>
@Html.Label("帳號")
<input>
標籤改寫要看其type
屬性為何,例如帳號是用type="text"
,則使用@Html.TextBox()
方法。改寫對照如下:
<input type="text" name="id" class="form-control" required />
@Html.TextBox("id", null, new { @class = "form-control", required = "required" })
這邊參數內容比較複雜,我們改寫完後移到方法上面看一下多載內容:
可以看到這個多載方法要給的參數是(name
,value
,htmlAttributes
),
name
參數會同時轉換成HTML標籤的name
與 id
屬性,
id
屬性主要是用在套用CSS樣式與使用JavaScript語法取得元素,這邊不會深入研究;
value
參數代表預設值,原本的標籤沒有設定故這邊填null
;
htmlAttributes
參數寫的方式是用new{ }
將標籤的其他屬性都加進來,
屬性之間使用逗號
分隔,另外因為class
本身是C#關鍵字所以必須用@
符號跳脫。
htmlAttributes
寫法有點類似HTML語法,但沒有辦法使用Visual Studio的Intellisense輔助選取,所以這種情況是否要使用HTML Helper來寫就見仁見智了。
<form>
使用@Html.BeginForm()
方法,改寫對照如下:
<form action="~/Helper/Login" method="post">
</form>
@using (Html.BeginForm("Login", "Helper", FormMethod.Post))
同樣我們看一下方法的參數內容:
要給的參數是(actionName
,controllerName
,method
),這邊應該就很好理解,要輸入的是(動作方法名稱,控制器名稱,請求方法)。外面用了using()
將HTML Helper方法包住,此用法是取代需要Html.EndForm()
的寫法,如下面Code:
@{Html.BeginForm("Login", "Helper", FormMethod.Post);}
form content...
@{Html.EndForm();}
看起來麻煩多了對吧?所以完整使用@using(Html.BeginForm())
的寫法就簡單囉,如果沒有加上using()
,執行時會發現多了不正常的內容,有興趣可以自行測試看看~
另外補充假如@Html.BeginForm()
方法不填入任何參數的話,預設使用Post傳遞變數,並且將表單傳送到與檢視同名的Action,以此例來說就會變成下列Code:
<form action="~/Helper/Index" method="post">
</form>
Login View中<a>
標籤的改寫方式與<input>
類似,這邊就不多提,使用的是@Html.ActionLink()
方法,對照如下:
<a href="~/Helper/Index" name="link" class="btn btn-sm btn-default">回登入畫面</a>
@Html.ActionLink("回登入畫面", "Index", null, new { name = "link", @class = "btn btn-sm btn-default" })
完整Code如下:
Index View
ViewBag.Title = "Index";
<h2>Index</h2>
<div class="container">
@using (Html.BeginForm("Login", "Helper", FormMethod.Post))
@Html.Label("帳號")
@Html.TextBox("id", null, new { @class = "form-control", required = "required" })
@Html.Label("密碼")
@Html.Password("password", null, new { @class = "form-control", required = "required" })
<input type="submit" name="submit" value="登入" class="btn btn-primary" />
Login View
ViewBag.Title = "Login";
<h2>Login</h2>
<div class="container">
<li>帳號: @ViewBag.id</li>
<li>密碼: @ViewBag.password</li>
@Html.ActionLink("回登入畫面", "Index", null, new { name = "link", @class = "btn btn-sm btn-default" })
● 強型別HTML Helper
在輸入HTML Helper方法時,眼尖的人可能會看到有些很像的方法是以For
結尾的,這些方法屬於強型別HTML Helper,寫法也不太一樣,有以下幾個重點:
須和View頁面的Model配合使用,且必須在@model
宣告明確的型別。
強型別 Helper可以和Model的屬性繫結,對照HTML生成的id
與name
屬性。
與一般HTML Helper相同可以指定標籤屬性。
使用強型別 Helper的好處在於容易Debug,且有Intellisense輔助。
常用的強型別方法對照表格如下:
HTML Helper方法
產生的HTML
我們用一個註冊的頁面來說明如何使用強型別Helper,首先建立一個Member
類別,並新增幾個會員資料會用到的屬性,Code如下。
Model:
public class Member
public string Id { get; set; }
public string Password { get; set; }
public int Age { get; set; }
public DateTime Birthday { get; set; }
public string Email { get; set; }
接著在HelperController
底下新增2個動作方法:Register()
是顯示註冊填寫表單畫面,使用GET請求;另一個同名的POST方法Register(Member member)
是當提交表單時,會將內容透過member
物件攜帶到View。這2個動作方法皆會導向同一個View畫面,Code如下。
Controller:
[HttpGet]
public ActionResult Register()
return View();
[HttpPost]
public ActionResult Register(Member member)
return View(member);
接著是重頭戲的View,在@model
宣告型別為Member
,這樣就可以使用強型別HTML Helper建立表單內的各個標籤內容。
@using HTMLHelperDemo.Models
@model Member
寫法是使用lambda expression的形式繫結Model的屬性,例如以下Code對照:
@Html.LabelFor(m => m.Id, "帳號")
生成HTML如下
<label for="Id">帳號</label>
這邊的m
指的就是Member
物件,Id
屬性會對應到label
標籤的for
屬性,for
屬性用途請參考這裡,不是本篇重點所以不多提了。
再舉例下列Code對照:
@Html.TextBoxFor(m => m.Birthday, new { @class = "form-control", type = "date" })
生成HTML如下
<input class="form-control" data-val="true" data-val-date="欄位 Birthday 必須是日期。" data-val-required="Birthday 欄位是必要項。" id="Birthday" name="Birthday" type="date" value="" />
Model的Birthday
屬性對應到input
標籤的id
與name
屬性,另外可以發現到,使用強型別Helper會針對Model屬性的型別,自動建立標籤內驗證相關的屬性。
ex: data-val="true" data-val-date="欄位 Birthday 必須是日期。" data-val-required="Birthday 欄位是必要項。"
其他內容就以此類推,完整Code如下:
View:
@using HTMLHelperDemo.Models
@model Member
ViewBag.Title = "Register";
<h2>Register</h2>
@using (Html.BeginForm())
<div class="container">
<div class="form-group">
@Html.LabelFor(m => m.Id, "帳號")
@Html.TextBoxFor(m => m.Id, new { @class = "form-control" })
<div class="form-group">
@Html.LabelFor(m => m.Password, "密碼")
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
<div class="form-group">
@Html.LabelFor(m => m.Age, "年齡")
@Html.TextBoxFor(m => m.Age, new { @class = "form-control" })
<div class="form-group">
@Html.LabelFor(m => m.Email, "電子信箱")
@Html.TextBoxFor(m => m.Email, new { @class = "form-control", type = "email" })
<div class="form-group">
@Html.LabelFor(m => m.Birthday, "生日")
@Html.TextBoxFor(m => m.Birthday, new { @class = "form-control", type = "date" })
<div class="form-group">
<input type="submit" value="註冊" class="btn btn-primary" />
@if (Model != null)
<div class="container">
<li>@Html.DisplayNameFor(m => m.Id) : @Html.DisplayFor(m => m.Id)</li>
<li>@Html.DisplayNameFor(m => m.Password) : @Html.DisplayFor(m => m.Password)</li>
<li>@Html.DisplayNameFor(m => m.Age) : @Html.DisplayFor(m => m.Age)</li>
<li>@Html.DisplayNameFor(m => m.Email) : @Html.DisplayFor(m => m.Email)</li>
<li>@Html.DisplayNameFor(m => m.Birthday) : @Html.DisplayFor(m => m.Birthday)</li>
最後面用一個if
條件判定Model非null
,才能顯示表單提交的內容。因為這邊使用同一個View畫面,但在一開始進入註冊頁面時,Model物件還沒有透過提交表單被建立,顯示提交內容就會有問題。
另外這邊示範了使用@Html.DisplayNameFor()
與 @Html.DisplayFor()
的用法,簡單來說這兩個方法分別會把Model的屬性 和 Model屬性的內容 顯示出來,不會帶任何標籤。
最後呈現結果如下:
今天利用建立簡單的登入與註冊頁面認識了HTML Helper基本的使用方式,也順便複習之前學到的內容,明天開始要進入資料庫的部分~那就明天見啦~
※小弟不才,在軟體的世界還只是個小菜雞,如果內容有任何謬誤或問題,還請各位大神前輩們多多批評指教~歡迎下方留言討論^^