[ASP.net MVC 4] 生成控制項的方式選擇(以文字方塊TextBox為例)
前言
有一段時間沒玩ASP.net MVC,最近接案又開始重溫起
把一些小小心得整理上來
要在ASP.net MVC的View裡產生控制項的話
大概有三種做法:※XXX為TextBox、DropDownList、CheckBox…等等自行代入
@Html.XXXFor()
@Html.XXX()
<input type=”” name=”” />
這三種各有特性,該挑選哪一個,請見以下說明
事前準備
在Models資料夾加入一個TestViewModel.cs
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebApplicationNullableBindTest.Models
{
public class TestViewModel
{
//方字方塊最常見和string型別binding
public string strMsg { get; set; }
}
}
在Controllers資料夾加入控制器HomeController.cs
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebApplicationNullableBindTest.Models;
namespace WebApplicationNullableBindTest.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(TestViewModel vm)
{
ViewData["showMsg"] = vm.strMsg;
return View(vm);
}
}
}
加入檢視
@*View宣告使用ViewModel,享受強型別的好處*@
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
@using(Html.BeginForm("Index","Home",FormMethod.Post)){
<!--裡面待會要放TextBox-->
<div>
</div>
<input type="submit" value="提交" />
<div>
剛剛輸入的值:@ViewData["showMsg"]
</div>
}
</body>
</html>
說明
1.只要View有宣告使用ViewModel
不管三種方式中的任何一種,只要控制項的name名稱和ViewModel(以本文為例就是TestViewModel類別)的屬性相同,控制項的值會自動Binding到ViewModel
所以在controller的HttpPost的Index()才會用TestViewModel當參數傳進去
public ActionResult Index(TestViewModel vm)
{
ViewData["showMsg"] = vm.strMsg;
return View(vm);
}
2. View自己對自己Post後
使用<input type=”” name=”” />的話,value會清空
@Html.XXX()和@Html.XXXFor()這兩種Html Helper,value不會清空
這情況很像以前開發Web Form時,使用Server Control和Html Control的差別
@*View宣告使用ViewModel,享受強型別的好處*@
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
@using(Html.BeginForm("Index","Home",FormMethod.Post)){
<!--裡面待會要放TextBox-->
<div>
<input type="text" name="strMsg" />
</div>
<input type="submit" value="提交" />
<div>
剛剛輸入的值:@ViewData["showMsg"]
</div>
}
</body>
</html>
使用@Html.XXX() Html Helper方式
@*View宣告使用ViewModel,享受強型別的好處*@
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
@using(Html.BeginForm("Index","Home",FormMethod.Post)){
<!--裡面待會要放TextBox-->
<div>
@Html.TextBox("strMsg")
</div>
<input type="submit" value="提交" />
<div>
剛剛輸入的值:@ViewData["showMsg"]
</div>
}
</body>
</html>
所以目前可歸納,開發時儘量使用Html Helper來生成控制項對使用者操作比較方便
2013.5.10追記,這個還要再搭配Post的Action方法,有沒有傳入相對應的類別(該類別有屬性名稱在畫面上),值才會被keep住
以本文為例
我在Models資料夾已加入一個TestViewModel類別
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebApplicationNullableBindTest.Models
{
public class TestViewModel
{
public string strMsg { get; set; }
}
}
畫面上可不用宣告使用ViewModel
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
</head>
<body>
<div>
@using(Html.BeginForm("Index","Home",FormMethod.Post)){
@Html.TextBox("strMsg")
<input type="submit" value="提交" />
}
</div>
</body>
</html>
Action方法傳入的參數必加TestViewModel,就可以keep住畫面上輸入的值了
public ActionResult Index(TestViewModel vm)
{
return View();
}
3. @Html.XXX()控制項的name給字串型別,@Html.XXXFor()控制項的name命名來自Model的屬性、有intellisense輔助
以下使用@Html.XXXFor()來生成控制項,雖然打字比@Html.XXX()多
@*View宣告使用ViewModel,享受強型別的好處*@
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
@using(Html.BeginForm("Index","Home",FormMethod.Post)){
<!--裡面待會要放TextBox-->
<div>
@Html.TextBoxFor(Model=>Model.strMsg)
</div>
<input type="submit" value="提交" />
<div>
剛剛輸入的值:@ViewData["showMsg"]
</div>
}
</body>
</html>
使用@Html.XXXFor()除了有intellisense好處(較不會打錯字)
還有如果當ViewModel的屬性更改名稱的話
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebApplicationNullableBindTest.Models
{
public class TestViewModel
{
public string strChangeMsg { get; set; }
}
}
View在編譯時期,Visual Studio即可得知錯誤,讓開發者方便更改錯誤地方
↑此特性是@Html.XXX()所沒有的
所以此點可歸納優先使用@Html.XXXFor()再來是@Html.XXX()
不過@Html.XXXFor()有個前提:須在View最上方用@model宣告ViewModel
總結
在View裡,優先產生控制項的使用順序
@Html.XXXFor()
↓
@Html.XXX()
↓
<input type=”” name=”” value=”” />
當然,這順序並不是絕對
個人在開發過程中有碰到bool?型別,View要用CheckBox來Binding
如果用@Html.CheckBoxFor(Model=>Model.屬性.HasValue?Model.屬性.Value:false)的話
程式會出錯:範本只能配合欄位存取、屬性存取、單一維度陣列索引或單一參數自訂索引子運算式使用。
↑改用@Html.CheckBox(“Model屬性名稱”)即可Binding bool?型別解決問題
至於ViewModel的各屬性型別如何適當地生成各種控制項,有空再整理一個指南
Html Helper表單控制項的MSDN文件:使用 HTML Helper 在 ASP.NET MVC 呈現表單