懂點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的回傳呢,這樣的數據傳遞如何在服務器端獲取。。。有時間再談了。
可以參考的文章: