[.NET MVC進階系列03] Views 視圖基礎


[注:此文對應Chapter 3:Views]

  一、View的功能:

  1.View用來呈現頁面UI,通過Controller來指定View:

   要注意的是,MVC和以前基於文件的Web應用不同,URL指向的並不是最終顯示UI的文件,

     在MVC中,和URL打交道的是Controller,而不是View,是通過Controller中的Action Method來指定要顯示的View

  2.Controller中指定View的規則:

        在Controller中返回值類型為ActionResult的Action Method可以指定一個用來顯示UI的View,

        返回視圖的代碼:return View([參數]);

    返回View的View方法有三種不同參數,對應不同需求:

       1)參數為空:return View()

    這種為最常用的格式,用來返回和Action方法名同名的默認視圖;

       2)參數為視圖文件名:return View("HelloWorld.cshtml")

         使用這種格式,可以將Action方法Url指向View/ControllName/HelloWorld.cshtml 

    即,可以將Action方法Url指向View/ControllName下,和Action不同名的View文件

    3)參數為任意位置視圖文件:return View("視圖相對路徑")

     在這種格式下,可以將Action方法對應的Url指向任意視圖文件

   Controller代碼:

1 public class HomeController : Controller
2     {
3         public ActionResult Sample()
4         {
5             ViewBag.Message = "Hello World, this is a Sample!";
6             return View("~/Views/Shared/Error.cshtml");
7         }
8     }

   上面的代碼中,HomeController的Action方法Sample(), 將Url: 域名/home/sample 指向了項目自動生成的Error視圖

   運行程序得到的效果(注意地址):

        

   

   二、ViewData和ViewBag

    1.ViewData 

    原則上,controller中的數據是通過ViewDataDictionary(字典類)類的對象ViewData來傳遞給View 

    如:ViewData["CurrentTime"] = DataTime.Now;

    2.ViewBag

    從MVC3開始,將上面的語法進行簡化,使用ViewBag動態包裝ViewData,允許我們使用下面的語法:

      ViewBag.CurrentTime = DataTime.Now

    這種寫法和上面的字典模式完全相同。

    注意:

    1)如果ViewBag.關鍵詞其中的關鍵字中有空格,則不能編譯通過;

    2)ViewBag不能直接作為動態參數進行傳值

     如: @Html.TextBox("name",ViewBag.Name)——錯誤!

        @Html.TextBox("name",ViewData["Nmae"]) —— 正確!

        @Html.TextBox("name",(string)ViewBag.Name)——正確!

    

   三、基於強類型的View(Strongly Typed Views)

    1.原理:

    ViewData是ViewDataDictionary對象,該類不同於普通Dictionary類,其中包含了一個Model property,允許

    從Controller中,將一個(只能是一個)指定對象傳到View中。

    這種方式不同於使用ViewBag,是強類型。不需要再進行類型指定,直接就可以使用該對象的屬性和方法。

   2.使用:

    1)將要傳到View中的對象作為參數給View()方法:

      如:return View(albums);

    2)在View中,用model接收該對象,直接包含新型信息,不需要再進行類型指定。

      @model IEnumerable<Album>

      <ul>

        @foreach(Album a in Model)

        { <li>@a.Title</li>}

      </ul>

     3.在View中添加命名空間引用

     1)直接在.cshtml文件中添加

      @using MvcMusicStore.Models

     2)在Views文件夾的web.config文件中添加,對整個Views文件夾中所有View都有效

      <pages pageBaseType="System.Web.Mvc.WebViewPage">

        <namespaces>

          。。。。

          <add namespace="MvcMusicStore.Models" />

        </namespaces>

      </pages>

    4.通過NuGet獲取書籍配套例程代碼:

     建好一個MVC4項目,【工具】——【庫程序包管理器】——【程序包管理控制台】

     在命令行中鍵入:Install-Package Wrox.ProMvc4.Views.AlbumList

     

     這將添加兩個文件夾到項目中,Album類和AlbumController在\Samples\AlbumList中,視圖文件Albums.cshtml在\View\Albums中

     對應的URL為:域名/albums/listweaklytyped和域名/albums/liststronglytyped

     分別非強類型和強類型方式訪問,可以通過代碼比較其區別

    

    四、View Models

    1.起因——Conroller默認只能傳遞一個強類型對象到View中:

     1)ViewData所繼承的ViewDataDictrionary類中,只能包含一個Model類,所以,每次只能從Controlller傳到View一個對象。

     2)View中,大多數情況下需要多個后台傳過來的對象來進行綁定顯示或操作,單個后台穿過來的類對象不夠用,而使用ViewBag

      的話,又失去了強類型的好處。

    2.解決方案:View Modles

      寫自定義的View modle class,將你需要的所有信息都包含其中。

     如:自定義一個購物車Modle類  

1 public class ShoppingCartViewModle
2 {
3     public IEnumerable<Product> Products {get;set;}
4     public decimal CartTotal {get; set;}
5     public string Message {get;set;}          
6 }

    這樣,就可以把你需要的所有相關購物車的所有信息綜合在一起傳遞給View,並且使用的強類型View方式

    @model  ShoppingCartViewModel

    接收到的就是從Controller傳過來的完整信息。

    3. 例子:

     建好一個MVC4項目,【工具】——【庫程序包管理器】——【程序包管理控制台】

     在命令行中鍵入:Install-Package Wrox.ProMvc4.Views.ViewModel

     執行成功后,同上面的例子,會在項目中增加兩個文件夾:

      /Samples/ShoppingCartViewModel  包含Product類、ShoppingCartViewModel類和控制器ShoppingCartController類

        /Views/ShoppingCart/ 包含對應的視圖Index.cshtml

      

      運行后的效果(域名/ShoppingCart)

      

  

    五、Razor View Engine

    簡單的介紹跳過去,直接寫核心的

    1. 代碼表達方式

    最重要的標示符在Razor中就是“@”

    1)代碼表達式

     如 :@對象名.屬性  ,等同於Web Form視圖中的<%: 對象名.屬性 %>

     *注:

       雖然Razor比較智能,能夠判斷大多數情況,自動判定到底是想要轉換后台代碼,還是直接顯示,

        但也會遇到混淆的時候,可以通過下面幾種方式來避免:

       A) @(后台代碼)

        通過給后台代碼加(),來強制將@要轉換的內容,和其后面要直接顯示的文本分開。

         B) @@將顯示為@文本

 

      2)HTML編碼(Html Encoding)

      為防止注入攻擊,Razor表達式會自動進行HTML編碼

      @{string message = "<script>alert('haacked!');</script>";}

      <span>@message</span>

      上面的HMTL View代碼在運行時會被解釋為:

      <span>&lt;script&gt;alert(&#39;haacked!&#39;);&lt;/script&gt;</span>

        這種HTML編碼是自動進行的。

      在某些情況下,需要取消HTML編碼,可以使用HtmlHelp,使用HtmlStirng對象或者Html.Raw()

      如:

        @{string message = "<strong>This is bold!</strong>";}

        <span>@Html.Raw(message)</span>

      這次,就不會再被轉碼,會直接顯示為:

      <span><strong>This is bold!</strong></span>

      另外,使用@Ajax.JavaScriptStringEncode來編碼和Javascript相關的用戶輸入,來防止注入攻擊,如:

<script type="text/javascript">
    $(function () {
        var message = 'Hello @Ajax.JavaScriptStringEncode(ViewBag.Username)';
        $("#message").html(message).show('slow');
    });
</script>

      3)代碼段:

       @{代碼段}

     2. Razor 語法:

     1)隱式代碼表達式:

      <span>@model.Message</span>

      又Razor自動判斷后面的.Message是text文本還是model的property

     2)顯示代碼表達式:

      <span>@(model).Message</span>

      在括號中的是后台代碼,其外的是文本

     3)不經Html轉碼的表達式:

      <span>@Html.Raw(model.Message)</span>

      前面提過,Razor為防止注入攻擊,自動對用戶輸入進行HTML轉碼,如果特殊情況下不用轉碼,需要寫成上面的格式

    4)代碼段:

      @{

          int  x = 123;

          string y = "hello!";

       }

    5)混合文本和標簽

      @foreach(var item in items)

      {

        <span> Item @item.Name.</span>

      }

    6)混合代碼和文本

     @if(showMessage)

      {

        <text>This is plain text </text>

      }

      或

     @if(showMessage)

      {

        @:This is plain text.

      }

     注意,后面的語法@:只能針對一行代碼

    7)顯示文本的@

     &#64; 或者 @@

    8)服務器端注釋:

     @*

      This is a multiline server side comment.
      @if (showMessage) {
        <h1>@ViewBag.Message</h1>
      }
      All of this is commented out.
     *@

    9)調用泛型函數(Generic Method)

     @(Html.SomeMethod<AType>()) 

     其實和顯式的Razor代碼表達式一樣,注意外面加()!

    3. Layouts 布局

    類似於Asp.net中的MasterPage(母板頁),用來設定統一外觀的。

    設定整體布局使用的是~/_ViewStart.cshtml,它會在所有View被加載之前加載,指定母版布局視圖

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}

    每個View下Controller對應的文件夾中,可以添加自己的_ViewStart.cshtml,用來指定獨自使用的布局視圖,采取就近原則(替View代根目錄中的);

    而且,Layout框架的賦值語句:Layout="。。。",也可以加到任意一個View文件中,作為此文件的單獨布局框架。

    1)@RenderBody()

    Layout Template View中的@RenderBody()用於占位。

    2)@RenderSection()

    一個Layout可以包含多個分塊(setions),例如,可以為Layout添加Footer分塊

    <footer>@RenderSection("Footer")</footer>

    在使用這個Layout的View中,需要加入@section Footer{..}代碼,來設置自己的footer,如:

    @section Footer{ @@Copyright 2001-2015, All Right Received. }

    但是,大多數時候,希望section都是可選的,可將其改為:

    <footer>@RenderSection("Footer", required: flase) </footer>

    更為通用的方式,是在設置可更改的Section時,配備一個默認的Section外觀:

    <footer>

      @if (IsSctionDefined("Footer"))

      {

        RenderSection("Footer");

      }

      else

      {

        <span>This is the default footer. </span>

      }

    </footer>

    

    六、Patial View

    部分View是不包含layout的局部View。

    通常用來作為配合Ajax進行局部刷新。

    例子:

      Install-Package Wrox.ProMvc4.Views.SpecifyingViews

    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM