文章出處

      最近實在是太忙,客戶丟了一個框架,沒有任何說明文檔,更沒有所謂的技術支持,一直忙于學習,最后好歹還有點頭緒,話不多說,MVC的學習是不能拉下的,就當前小白的我,認為MVC中的M并不是想象中的那樣簡單,一般用作前后臺的數據交互。

什么是模型?什么是模型綁定?

微軟出的《ASP.NET MVC 5編程實戰》中有講到,模型分領域模型、視圖模型。個人理解視圖模型就是一個數據庫對應的實體類。領域模型狹義的來說包括視圖模型和一些其他的屬性。

       視圖傳遞參數+值(或實體對象),Action中接收。看似是一瞬間完成的。中間其實是需要經過兩個步驟,①通過實現IValueProvider接口來獲取視圖中(Form、RouteData、QueryString、HttpFileCollection)請求值。②在通過實現IModelBind中的方法將這些獲取的請求參數、值綁定到Action中對應的形參上。同樣這里接口中方法都是默認去調用的,如果有需要,可以進行自定義編寫實現其接口的方法。

比如,最常見的 將數據庫中A表的部分數據顯示在視圖V中,然后進行增刪該查操作。這里在視圖V中,最上面會引用 該表的實體類@model  項目名.文件夾.實體類,再根據Razor語法,就可以用Lambda表達式點出來 該表的列名

創建--前臺表單數據提交到Controller

@model MVC_plug.Models.Students
@{
    ViewBag.Title = "Create";
}
<h2>Create</h2>
@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>Students</legend>  
        <div class="editor-label">
            @Html.LabelFor(model => model.Stu_Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Stu_Name)
            @Html.ValidationMessageFor(model => model.Stu_Name)
        </div>

這里 瀏覽器解析Razor 語法是 將 BeginForm 解析為From表單,對于HTML來說是,是不存在實體類之說的,表單提交的值僅僅是以鍵值對的方式進行存儲后提交到指定的Action中.也就是將視圖中的請求參數與action中的形參進行匹配、綁定。這就是簡單模型綁定。

1 .在Controller中對應的Action的方法體中 將 Student 作為參數來接收

        [HttpPost]
        public ActionResult Create(Students students)
        {
            if (ModelState.IsValid)
            {
                db.Students.Add(students);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(students);
        }

既然View中不存在將提交的內容綁定到 實體類中,那么輸入的數據為什么在Action的參數Student中可以點出來? 實際上 View 中Post提交的數據 是以鍵值對的方式進行存儲,然后映射到提交的Action中的 Student中,前提是 View中的鍵名(Name名字)必須要等于 實體類型的屬性名,否則無法綁定     

2.在Controller中對應的Action的方法體中直接設置參數來接收值 ()

 public ActionResult Create(string Stu_Name,string Tel,string phone)

運行項目,其中Stu_Name、Tel 有值,phone 無值,當然這只是佐證,如果在前臺的View 中設置的名字不一樣,后臺用Student去接收,同樣也會得到空值。

后臺傳遞數據到前臺

1. 顯示某數據列表 ,同樣是后臺Controller 將 查詢的結果 賦值給一個實體類對象,用反射也好,反序也行,再 Return View(實體類); 

    前臺最上面要引用 @model 指向實體類 來接收傳遞的數據,因為是同一個實體,直接映射到前臺,最后View 中進行顯示即可

2. 當然還可以選擇 ViewData 和ViewBag 在后臺的Action中賦值,然后在View中接收,關于這兩者的比較,這里簡單的整理下

    ViewData 的 ViewDataDictionary 是一個特殊的字典類,當在控制器中使用 ViewData["CurrentTime"] = DateTime.Now; 其實是將這個值以鍵值對的形式進行存儲

    ViewBag不再是字典的鍵值對結構,而是dynamic動態類型,它會在程序運行的時候動態解析

MVC 高級編程中提高兩者的區別

①只有當要訪問的關鍵字是一個有效的C#標識符時,ViewBag 才起作用。 

例如,如果在ViewData["Key With Spaces"]中存放一個值,那么就不能使用ViewBag訪問。因為這樣根本就無法通過編譯。

②動態值不能作為一個參數傳遞給擴展方法。因為C#編譯器為了選擇正確的擴展方法,在編譯時必須知道每一個參數的真正類型。如果其中任何一個參數是動態的,那么就不會通過編譯。

例如,這行代碼就會編譯失敗:@Html.TextBox("name",ViewBag.Name)。要使這行代碼通過編譯有兩種方法:第一是使用ViewData["Name"],第二是把ViewBag.Name值轉換為一個具體的型:(string)ViewBag.Name 。

說白了,ViewBag 就是在ViewData的升級版,兩者只能在Action中起作用,當然,兩者的數據是可以相互訪問。ViewBag的底層是ViewData,所以當兩者定義同一屬性不同值的時候,視圖中顯示的值永遠是ViewData所定義的值

        // GET: Test
        public ActionResult Index()
        {
                                  
            ViewBag.Name = "顓頊viewbag";
            ViewData["Name"] = "顓頊viewdata";
            return View();
        }

前臺視圖中顯示的值,均是  顓頊viewdata

    @Html.TextBox("Name",(string)ViewBag.Name)
    <br/>
    @Html.TextBox("Name",ViewData["Name"])

此外當用 TextBoxFor +強類型視圖時,若在控制器中給實體類賦值,視圖中又用New{ Value=“” } 來賦值,則實體對象中的值將被覆蓋。

        public ActionResult Index()
        {

            Test te = new Test();
            te.Name = "顓頊";
            TestViewModel testViewModel = new TestViewModel()
            {
                test = te,
                Tests = new List<Test>()
            };
                       
            ViewBag.Name = "顓頊viewbag";
            ViewData["Name"] = "顓頊viewdata";

            return View(testViewModel);
        }

如下視圖均顯示顓頊viewdata(Value中首字母V需大寫)

 

    @Html.TextBoxFor(m => m.test.Name,new { Value= ViewData["Name"]})
    <br />
    @Html.TextBoxFor(m => m.test.Name, new { Value = (string)ViewBag.Name })

 

市人皆大笑,舉手揶揄之

 


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()