iT邦幫忙

2022 iThome 鐵人賽

DAY 8
1
Software Development

C# ASP.NET MVC實作: 30天打造屬於你的網站應用程式系列 第 8

(DAY 8)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-HTML Helper

  • 分享至 

  • xImage
  •  

● HTML Helper簡介

HTML Helper是用於快速產生HTML標籤與內容的工具,寫法會比直接寫HTML語法簡潔,如果靈活運用可以節省許多開發時間。HTML Helper常用方法對照表格如下:

HTML Helper方法 產生的HTML
@Html.ActionLink() <a href="..."></a>
@Html.BeginForm() <form action="..." method="..."></form>
@Html.Label() <label></label>
@Html.CheckBox() <input type="checkbox" />
@Html.RadioButton() <input type="radio" />
@Html.Hidden() <input type="hidden" />
@Html.TextBox() <input type="text" />
@Html.Password() <input type="password" />

上述這些方法如果想要增加多個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頁面,所以先照下面步驟完成

  1. 新增名為HelperController的控制器,建立後Code如下:
    public class HelperController : Controller
    {
        // GET: Helper
        public ActionResult Index()
        {
            return View();
        }
    }
  1. 新增 Index()方法的View,一樣照預設套用版面配置頁就好

  2. 在View添加下列HTML程式碼,使用form表單將要提交的內容包住,form提交指定的路徑是~/Helper/Login,並使用POST請求:


@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div class="container">
    <form action="~/Helper/Login" method="post">
        <div>
            <label>帳號:</label>
            <input type="text" name="id" class="form-control" required />
        </div>
        <br />
        <div>
            <label>密碼:</label>
            <input type="password" name="password" class="form-control" required />
        </div>
        <br />
        <div>
            <input type="submit" name="submit" value="登入" class="btn btn-primary" />
        </div>

    </form>
</div>

補充說明一下,帳號和密碼的欄位都有一個required的屬性,這代表在登入時會先驗證欄位是否有輸入,執行畫面如下:

  1. 新增名為Login的動作方法,且會帶入帳號和密碼的兩個參數id & password,還記得參數名稱是對應HTML標籤內的name屬性嗎?另外這裡使用ViewBag攜帶參數到登入後的View。
        [HttpPost]
        public ActionResult Login(string id ,string password)
        {
            ViewBag.id = id;
            ViewBag.password = password;
            return View();
        }
  1. 新增Login方法的View,這裡簡單顯示登入的帳號密碼資料就好,另外增加一個可以回登入畫面的連結,Code如下:

@{
    ViewBag.Title = "Login";
}

<h2>Login</h2>

<div class="container">
    <ul>
        <li>帳號: @ViewBag.id</li>
        <li>密碼: @ViewBag.password</li>
    </ul>
    <div>
        <a href="~/Helper/Index" name="link" class="btn btn-sm btn-default">回登入畫面</a>
    </div>
</div>

到這邊都算是前幾天的教學內容,可以先執行操作看看是否能正常輸入帳密,登入後能顯示資料的畫面,按下回登入畫面連結也能回到登入畫面。如果有問題先檢視前面步驟有沒有錯誤。

● 使用HTML Helper 改寫畫面

接著我們來將原本View的程式碼改用HTML Helper呈現,先看到Index的View,可以改寫的部分是<form><label><input>標籤,另外在Login的View可以改寫<a>標籤。

  1. <label>標籤這邊沒有加任何屬性所以最簡單,改寫對照如下:
<label>帳號:</label>
@Html.Label("帳號")
  1. <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來寫就見仁見智了。

  1. <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>
  1. Login View中<a>標籤的改寫方式與<input>類似,這邊就不多提,使用的是@Html.ActionLink()方法,對照如下:
    <div>
        <a href="~/Helper/Index" name="link" class="btn btn-sm btn-default">回登入畫面</a>
    </div>
    <div>
        @Html.ActionLink("回登入畫面", "Index", null, new { name = "link", @class = "btn btn-sm btn-default" })
    </div>

完整Code如下:

Index View


@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<div class="container">
    @using (Html.BeginForm("Login", "Helper", FormMethod.Post))
    {
        <div>
            @Html.Label("帳號")
            @Html.TextBox("id", null, new { @class = "form-control", required = "required" })
        </div>
        <br />
        <div>
            @Html.Label("密碼")
            @Html.Password("password", null, new { @class = "form-control", required = "required" })
        </div>
        <br />
        <div>
            <input type="submit" name="submit" value="登入" class="btn btn-primary" />
        </div>
    }
</div>

Login View


@{
    ViewBag.Title = "Login";
}

<h2>Login</h2>

<div class="container">
    <ul>
        <li>帳號: @ViewBag.id</li>
        <li>密碼: @ViewBag.password</li>
    </ul>

    <div>
        @Html.ActionLink("回登入畫面", "Index", null, new { name = "link", @class = "btn btn-sm btn-default" })
    </div>
</div>

● 強型別HTML Helper

在輸入HTML Helper方法時,眼尖的人可能會看到有些很像的方法是以For結尾的,這些方法屬於強型別HTML Helper,寫法也不太一樣,有以下幾個重點:

  1. 須和View頁面的Model配合使用,且必須在@model宣告明確的型別。
  2. 強型別 Helper可以和Model的屬性繫結,對照HTML生成的idname屬性。
  3. 與一般HTML Helper相同可以指定標籤屬性。
  4. 使用強型別 Helper的好處在於容易Debug,且有Intellisense輔助。

常用的強型別方法對照表格如下:

HTML Helper方法 產生的HTML
@Html.DisplayNameFor() 顯示物件Model屬性的名稱
@Html.DisplayFor() 顯示物件Model屬性的資料內容
@Html.EditorFor() 直接依照物件Model屬性產生對應<input>欄位
@Html.LabelFor() <label></label>
@Html.CheckBoxFor() <input type="checkbox" />
@Html.RadioButtonFor() <input type="radio" />
@Html.HiddenFor() <input type="hidden" />
@Html.TextBoxFor() <input type="text" />
@Html.PasswordFor() <input type="password" />

● 範例-註冊頁面


我們用一個註冊的頁面來說明如何使用強型別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>
        <div class="form-group">
            @Html.LabelFor(m => m.Password, "密碼")
            @Html.PasswordFor(m => m.Password, new { @class = "form-control" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Age, "年齡")
            @Html.TextBoxFor(m => m.Age, new { @class = "form-control" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Email, "電子信箱")
            @Html.TextBoxFor(m => m.Email, new { @class = "form-control", type = "email" })
        </div>
        <div class="form-group">
            @Html.LabelFor(m => m.Birthday, "生日")
            @Html.TextBoxFor(m => m.Birthday, new { @class = "form-control", type = "date" })
        </div>
        <div class="form-group">
            <input type="submit" value="註冊" class="btn btn-primary" />
        </div>
    </div>
}

@if (Model != null)
{
    <hr />
    <div class="container">
        <ul>
            <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>
        </ul>
    </div>
}

最後面用一個if條件判定Model非null,才能顯示表單提交的內容。因為這邊使用同一個View畫面,但在一開始進入註冊頁面時,Model物件還沒有透過提交表單被建立,顯示提交內容就會有問題。

另外這邊示範了使用@Html.DisplayNameFor()@Html.DisplayFor()的用法,簡單來說這兩個方法分別會把Model的屬性 和 Model屬性的內容 顯示出來,不會帶任何標籤。

最後呈現結果如下:

● 小結

今天利用建立簡單的登入與註冊頁面認識了HTML Helper基本的使用方式,也順便複習之前學到的內容,明天開始要進入資料庫的部分~那就明天見啦~

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


上一篇
(DAY 7)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-Bootstrap套件
下一篇
(DAY 9)C# ASP .NET MVC實作: 30天打造屬於你的網站應用程式-資料驗證
系列文
C# ASP.NET MVC實作: 30天打造屬於你的網站應用程式30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言