懂點MVC的人都知道MVC 的機制是訪問Contoller下的Action,由Action組織好頁面需要的資料然後返回視圖(return View()/return PartialView())或資料(return Content(“blah”)/ return Json(…)),有的時候返回視圖的同時連帶返回資料以供頁面使用(return View(model))。
其實Controller與View之間的傳值有很多形式啦,除了傳統的Retrun語句向頁面返回資料,還可以通過 ViewData,ViewBag等。它們的使用在Razor句法與非Razor句法中稍有不同。
比如妳建立一個MVC程式,在初始的Home/Index Action裡而,就有如下代碼:
public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); }
其中通過ViewBag向頁面傳送一句文本。那麼在頁面,我們通過直接書寫相同的系統變數名稱來訪問:
<h2><%: ViewBag.Message %></h2>
再看看ViewData,比如我把剛才通過ViewBag傳送的值通過ViewData來完成。
所以在Home/Index 這個Action裡而,修改代碼如下:
public ActionResult Index() { //ViewBag.Message = "Welcome to ASP.NET MVC!"; ViewData["Message"] = "Welcome to ASP.NET MVC!!"; return View(); }
它是以數組的形式,隨便取了個遊標名以便訪問資料,這裡定義了一個名為“Message”的文本儲存到了ViewData裡而。
然後在頁面,同樣使用相同的語句來訪問:
<h2><%: ViewData ["Message"] %></h2>
如果想傳遞多個變數,直接書寫另一個變數就行,然後在頁面訪問變數名擷取資料。
有意思的是,貌似ViewBag和ViewData 其實是同種東西的不同表示,比如我們定義:
public ActionResult Index() { ViewBag.Message = "ViewBag.Message"; return View(); }
在頁面,既可以通過ViewBag的句法來訪問,也可以通過ViewData的句法來訪問。反之亦可。
<h2><%: ViewData ["Message"] %></h2><h2><%: ViewBag.Message %></h2>
但其實上而這些都不是本文我想說的,下面進入主題,如果在JavaScript代碼中訪問這些資料,進一步說,如何訪問由Action 傳到頁面的資料。
在由<Script>包圍的指令碼代碼中,自然想到用相同的文法來訪問。我們用ViewData進行傳遞:
public ActionResult Index() { ViewData["message"] = "Data from server."; return View(); }
然後在JS代碼中,看起來應該是這樣子的:
<script > $(function() { var data = <%:ViewData["message"] %>; }) </script>
然後一運行發現報錯,
但神奇的是我們已經完成任務了。但其實仔細看是不正確的,因為等號後面的語句,不是正常的JavaScript語句。
那為了避免報錯同時使代碼正常,我們需要用引號將它包起來,所以看起來應該是這樣子的:
var data = ' <%:ViewData["message"] %>';
對於這樣的簡單資料,似乎就已經夠了。但一般Action返回的都是模型(Model)等複雜類型的資料。
首先,為了說明方便,到Model檔案夾下建立一個類檔案,叫PersonalModel,為了簡單,其內容大概是這樣的:
public class PersonModel { public string Name { get; set; } public int Age { get; set; } }
很簡單的對象,只包含一個字串類型的Name屬性和一個整數型別的Age屬性。
下面再寫一個方法產生一些靜資料,真實情況下這些資料可能是從資料庫取的。為了調用方便這個方法我寫在了HomeController 類裡面,其樣子看起來似乎是這樣子的:
static List<PersonModel> DummyData() { var data = new List<PersonModel>() { new PersonModel() { Name = "Tom", Age = 20 }, new PersonModel() { Name = "Cat", Age = 5 } }; return data; }
然後我們去修改Index Action,讓它返回資料。
public ActionResult Index() { var data=DummyData(); return View(data); }
最後我們再去頁面的JS程式碼片段裡,接收它。
<script > $(function() { var model = <%= new JavaScriptSerializer().Serialize(Model) %>; debugger; }) </script>
加了個debugger是為了呆會在瀏覽器裡進入偵錯模式查看資料的方便。
然後我們再到瀏覽器查看是否得到了資料(記得瀏覽器是偵錯模式,按F12進入)。
我們成功在JS程式碼片段裡獲得了傳來的資料並序例化成了Json格式。
然後可以通過類似下面的語句來調用。
<script > $(function() { var model = <%= new JavaScriptSerializer().Serialize(Model) %>; alert(model[0].Name); debugger; }) </script>
上面說的只是在JS裡訪問,其實這倒不是主要的需求了,只是我們習慣了在頁面的使用方法而突然要在JS裡訪問這些資料時不知道怎麼辦。
那在頁面裡,如何對這種集合類型的資料進行訪問。我們都知道向頁面傳送一個Model時的情形。
比如下面我們修改Index Action讓它只返回一條資料。類型當然為PersonModle了。
public ActionResult Index() { //var data=DummyData(); var data = new PersonModel() { Name = "Tom", Age = 20 }; return View(data); }
注意之前的data(注釋掉的那個)的類型是List<PersonModel>,它是個集合類型,而現在是PersonModle類型的。理解這點對我們在頁面如何正確擷取資料非常重要。
然後再去把頁面修改為強型別的,經便接收資料(如妳所見,上面我們在JS中想要獲得資料時,不需要頁面是強型別的)。
之前的頁面類型看起來是這個樣子的:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
現在我們要將它修改為這個樣子的:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcApplication17.Models.PersonModel>" %>
然後我們就可以在頁面使用傳遞來的資料了,用類似這樣的文法:
<p> Name:<%= Html.DisplayFor(model=>model.Name) %> Age:<%= Html.DisplayFor(model=>model.Age) %></p>
當傳遞來的是集合類型的資料時,就無法這樣簡單的訪問了,需要遍曆集合,取到裡面的單條資料後才可使用。
下面我們就來看一下集合類型時的情境。
修改Index Action返回的資料為原來的那個:
public ActionResult Index() { var data=DummyData(); return View(data); }
然後再去把頁面的接收類型相應修改成這個樣子的:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MvcApplication17.Models.PersonModel>>" %>
最後在頁面,我們需要遍曆這個集合來取得資料,可以用類似這樣的句法:
<% foreach(var item in Model) { %> <p> Name:<%= Html.DisplayFor(n=>item.Name) %> Age:<%= Html.DisplayFor(n=>item.Age) %> </p> <% } %>
這裡還只是簡單談到了MVC中資料由伺服器端到頁面的傳遞,其實更難的是將資料傳回伺服器綁定到模型。當然,如果妳用表單,直接一個Submit,所有的事情架構都為妳做了,模型很容易就綁定好了。但如果妳的頁面有個多模型呢,妳不想用Submit而想自己寫Ajax的回傳呢,這樣的資料傳遞如何在伺服器端擷取。。。有時間再談了。
可以參考的文章:
- ASP.NET MVC using ViewData in javascript(StackOverFlow)
- Using ASP.NET MVC v2 EditorFor and DisplayFor with IEnumerable<T> Generic types