Model Binding-ViewBag ViewData ViewData.Mode TempData
資料從Controller如何傳給View的技術稱之為Model Binding,
此文章主要說明Model Binding、ViewBag、ViewData、ViewData.Mode、TempData的使用。
一、Model Binding的舉例
1、首先先新增一個預設的MVC專案
2、於Controller準備一個Model,帶給View的datatime
public ActionResult Index()
{
return View(DateTime.Now.AddDays(-1d));
}
3、View先不呼叫helper,先改成如下
@model DateTime? @Model
4、執行畫面為
5、接下來使用helper(@Html.DisplayFor()),View改為強型別
@model DateTime? @Html.DisplayFor(model => model)
6、執行畫面為
會發現html呈現都一樣,可知此@Html.DisplayFor()只負責將資料輸出成字串而已
7、心得
注意:@Model相等於DisplayFor()擴充方法裡的model變數,
初期我看保哥的書完全搞混不知道@Model、@model、model的差別,
自己慢慢學習之後,現在懂了,@Model就是用來接收從Controller傳來的模型資料、
@model為指示詞表示所接到的模型資料型態為何、而存在於擴充方法裡的model只是個變數,
並不是關鍵字,而該變數其實就是@Model經由委派傳給model變數來處理的。
其中牽扯到的技術,是基本功,我知道很複雜,但知道來龍去脈時,
我只能說「超爽der~~~」
二、ViewBag
當Controller為
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View("~/Views/Home/About.cshtml");
}
View為
<h3>@ViewBag.Message</h3> <p>Use this area to provide additional information.</p>
則@ViewBag.Message將會等於Your application description page.
ViewBag 值的型別是 object,如果你的 object 的內容是可以轉成字串,
那你就可以將之轉成字串型別,並可操作字串方法了,如下
var myBoolValue = @Viewbag.MyBoolValue.ToString().ToLower();
三、ViewData
1、預設以字串傳遞
當Controller為
public ActionResult About()
{
ViewData["context"] = "a word";
return View();
}
View為
<h3>@ViewData["context"]</h3> <p>Use this area to provide additional information.</p>
則@ViewData["context"]將會等於a word
2、以非字串傳遞須轉型
(1)、另一個例子,當ViewData內容非字串時
當Controller為
public ActionResult About()
{
ViewData["the_bool"] = true;
return View();
}
此ViewData為弱型別,所以ViewData必須明確轉型
@{
bool? myBoolean = (bool?)@ViewData["the_bool"];
}
@{
if (myBoolean != null)
{
<p>boolean 值為@(ViewData["the_bool"])</p>
}
}
(2)、承上例,但View此次使用 as 關鍵字轉型
@{
bool? myBoolean = @ViewData["the_bool"] as bool?;
myBoolean = myBoolean ?? false;
}
@if (myBoolean != null)
{
<p>boolean 值為@(ViewData["the_bool"])</p>
}
3、或使用dynamic來宣告,dynamic關鍵字在編譯時被視為實際型別,
而被宣告的型別物件(myBoolean)又可在執行時期自動轉成目標型別。
<p>Use this area to provide additional information.</p>
@{
dynamic myBoolean = @ViewData["the_bool"];
}
@{
if (myBoolean != null)
{
<p>boolean 值為@(ViewData["the_bool"])</p>
}
}
成功畫面為
否則會出現錯誤
4、ViewData可與ViewBag互相透通
(1)單純傳遞字串時可互相透通
例如:
Controller為
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
View可為
@ViewData["Message"]
反過來
Controller為
public ActionResult About()
{
ViewData["Message"] = "Your application description page.";
return View();
}
View可為
@ViewBag.Message
(2)如果是傳遞物件時
於View裡使用ViewBag還算順利,因為ViewBag會幫你自動轉型
在Model準備
namespace WebApplication1.Models
{
public class product
{
public string Id;
public string name;
public product(string a, string b)
{
Id = a;
name = b;
}
}
}
Controller準備
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
product flower = new product("000","flower");
ViewData["Thing"] = flower;
return View();
}
}
}
View可為
@ViewBag.Thing.Id
但反過來可沒那麼順利了,使用ViewData時必須要手動轉型才可
Controller改為
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
product flower = new product("000","flower");
ViewBag.Thing = flower;
return View();
}
}
}
View改為
@{
var Thing = ViewData["Thing"] as WebApplication1.Models.product;
}
@Thing.Id
5、ViewData特性
ViewData有一個特性,就是他只會存在這次的Http中要求而已。
ViewData只在當前的Action中有效,生命週期和View相同。
四、ViewData.Model
1、一般字串
Controller為
public ActionResult Contact()
{
List<string> aList = new List<string>();
aList.Add("List A");
aList.Add("List B");
ViewData.Model = aList;
return View();
}
View為
@model List<string> @{ foreach (var item in @Model) { <p>@item</p> } }
上述ViewData.Model的@model宣告為強型別
ViewData.Model等於ViewPage的Model
也就是Controller可改寫為
public ActionResult Contact()
{
List<string> aList = new List<string>();
aList.Add("List A");
aList.Add("List B");
return View(aList);
}
2、另一例子為加入類別並使用強型別來帶出資料
準備一個Model為
namespace WebApplication1.Models
{
public class product
{
public string Id;
public string name;
public product(string a, string b)
{
Id = a;
name = b;
}
}
}
準備Controller為
using System.Collections.Generic;
using System.Web.Mvc;
using WebApplication1.Models;
namespace WebApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
List<product> aList = new List<product>();
product p = new product("a","b");
aList.Add(p);
return View(aList);
}
}
}
而View為
@model List<WebApplication1.Models.product> @Model.FirstOrDefault().Id
畫面為
此例子就可充分利用Intellisense的好處了
五、TempData
1、TempData只能被取用一次,用完即被清除。
Controller為
public ActionResult Contact()
{
List<string> aList = new List<string>();
aList.Add("List A");
aList.Add("List B");
TempData["myData"] = aList;
TempData["message"] = "我是Message";
return View();
}
public ActionResult About()
{
return View();
}
Contact view為
@{ List<string> aList = (List<string>)TempData["myData"]; } @{ foreach (var item in aList) { <p>@item</p> } } @Html.ActionLink("About", "About") <p>已取用myData,但未取用message</p>
About view為
@{
List<string> aList = (List<string>)TempData["myData"];
}
@{
if (aList != null)
{
foreach (var item in aList)
{
<p>@item</p>
}
}
}
@TempData["message"]
<p>已取用的myData會被清除,但未取用過的message會秀出</p>
2、如果TempData被讀取了,但不想要被刪除如何做?
可以在使用TempData資料後,再使用TempData.Keep();方法,
可保住所有session值,如果只想保留特定值的話,
則可使用TempData.Keep(string Key)方法;
承上例,View可改為
@{
List<string> aList = (List<string>)TempData["myData"];
TempData.Keep();
}
@{
if (aList != null)
{
foreach (var item in aList)
{
<p>@item</p>
}
}
}
@TempData["message"]
參考資料: