上述這些方法如果想要增加多個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標籤的nameid 屬性,
    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生成的idname屬性。
  • 與一般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標籤的idname屬性,另外可以發現到,使用強型別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基本的使用方式,也順便複習之前學到的內容,明天開始要進入資料庫的部分~那就明天見啦~

    ※小弟不才,在軟體的世界還只是個小菜雞,如果內容有任何謬誤或問題,還請各位大神前輩們多多批評指教~歡迎下方留言討論^^