3-6.ASP.NET Core MVC 入門教學 - 使用ViewData和ViewBag傳遞資料

ASP.NET Core MVC 入門教學

上一節我們學到了用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是取不到上一次的值,簡單來說就是每次讀取都是新的,必須重新設定




Copyright © 凱哥寫程式 2022 | Powered by TalllKai ❤