上一節我們學到了用Model來傳遞資料
這一節來教另外幾種更簡單方便的從Controller傳遞資料到跨各個View的方法
就是利用ViewData或ViewBag
不過ViewData跟ViewBag其實是同一種東西,只是寫法上不一樣而已
我們先來看ViewData的用法,以下之前幾節寫的Demo,在回傳View()之前使用了ViewData並給值
namespace WebApplication1.Controllers
{
public class DemoController : Controller
{
public IActionResult Index()
{
ViewData["title"] = "這是從Controller就設定的值";
return View();
}
public IActionResult View2()
{
return View();
}
}
}
那在Index.cshtml怎麼把這個值給拿掉並印在畫面上呢?
這是我第一個建立的View
<br />
@ViewData["title"] //就這麼簡單
就很簡單直接,直接在你想要用的地方打上你給的ViewData+參數即可,以下看畫面
就可以看到畫面印出來我們剛剛在Controller設定的內容了
接著來看看ViewBag如何使用,如下
namespace WebApplication1.Controllers
{
public class DemoController : Controller
{
public IActionResult Index()
{
ViewBag.title = "這是從Controller就設定的ViewBag值";
return View();
}
public IActionResult View2()
{
return View();
}
}
}
這是我第一個建立的View
<br />
@ViewBag.title
沒錯,基本上就真的是寫法不一樣而已,其實兩個可以說是一模一樣的東西
一樣到什麼地步呢?其實兩個的參數是共用的,指向同一個位置,以下示範
namespace WebApplication1.Controllers
{
public class DemoController : Controller
{
public IActionResult Index()
{
ViewBag.Title = "這是從Controller就設定的ViewBag值";
ViewData["title"] = "這是從Controller就設定的ViewBag值,但我又用ViewData來設定";
return View();
}
public IActionResult View2()
{
return View();
}
}
}
我這邊使用了ViewBag.Title
先設定了一個內容,隨後又用ViewData["title"]
設定了一個內容
但兩者的參數都是title,另外順便說明一下,這邊大小寫都視為同一個參數
之後回到View,再把兩個都印出來看看
這是我第一個建立的View
<br />
@ViewBag.Title
<br />
@ViewData["title"]
可以看到,兩個印出來的值是一模一樣的,代表ViewData["title"]
蓋掉了ViewBag.Title
的值
那使用Model傳遞資料和ViewData跟ViewBag傳遞資料,通常要用哪個好呢
就我個人而言,重要且龐大的資料我會使用Model的方式來傳遞
不太重要或簡單直接的資料,我會使用ViewData跟ViewBag,其實我們可以看到ViewData跟ViewBag是不用宣告型別就可以使用的
對於這種不用宣告的其實是盡量少用,因為會造成以後維護困難,要用也是用在很簡單的地方
哪裡是很簡單的地方呢?其實範例一開始就有使用了,我們看到Views/Shared/_Layout.cshtml
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>@ViewData["Title"] - WebApplication1</title>
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
<link rel="stylesheet" href="~/WebApplication1.styles.css" asp-append-version="true" />
</head>
他把它用在了網頁標題的地方,然後分別在Index.cshtml跟Privacy.cshtml中設定,如下
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://learn.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
@{
ViewData["Title"] = "Privacy Policy";
}
<h1>@ViewData["Title"]</h1>
<p>Use this page to detail your site's privacy policy.</p>
沒錯,這就是一個很好的例子,用在基本上不可能出錯,且非常單純直覺的地方,才會使用ViewData或ViewBag來傳值
只要一複雜或者龐大的資料,我們則會選用上一節課教的Model來傳值
那這時候可能有人會問ViewData或ViewBag這兩個之間該用哪個好,分別使用的時機是什麼
答案是,依各人喜好即可
但ViewBag在使用上會比ViewData更隨意
我們仔細看ViewBag的資料型別會是dynamic,所以基本上可以隨便亂用,但代價可能造成維護困難
而ViewData則是object,所以在使用上會需要再轉型定義一下才能用,如下示範
可以看到ViewData直接做數字加總時,會出現紅色警告線,無法正常編譯,這時我們需要加個型別才能夠編譯過,如下
public IActionResult View2()
{
ViewBag.Number1 = 10;
int ViewBag做運算 = 10 + ViewBag.Number1;
ViewData["Number2"] = 10;
int ViewData做運算 = 10 + (int)ViewData["Number2"];
return View();
}
所以ViewBag在使用上是更隨意一些,可以不同型別亂加起來都行,都不會告警,只不過在運行階段會報錯而已
兩者的差別大致上就是在這裡,其他基本大致都差不多,所以真的就是看你自己喜好選擇用哪個就好
最後就是,這兩個的生命週期都只有在這次的Request之中,使用者下次的Request是取不到上一次的值,簡單來說就是每次讀取都是新的,必須重新設定