菜鳥學ASP.NET MVC4入門筆記


  ASP.NET MVC 是微軟官方提供的以MVC模式為基礎的ASP.NET Web應用程序(Web Application)框架,它由Castle的MonoRail而來。

MVC 編程模式

       MVC 是三種 ASP.NET 編程模式中的一種。

       MVC 是一種使用 MVC(Model View Controller 模型-視圖-控制器)設計創建 Web 應用程序的模式。

    (1)Model(模型)表示應用程序核心(比如數據庫記錄列表)。

    (2)View(視圖)顯示數據(數據庫記錄)。

    (3)Controller(控制器)處理輸入(寫入數據庫記錄)。

       MVC 模式同時提供了對 HTML、CSS 和 JavaScript 的完全控制。Model(模型)是應用程序中用於處理應用程序數據邏輯的部分。通常模型對象負責在數據庫中存取數據。View(視圖)是應用程序中處理數據顯示的部分。通常視圖是依據模型數據創建的。Controller(控制器)是應用程序中處理用戶交互的部分。通常控制器負責從視圖讀取數據,控制用戶輸入,並向模型發送數據。       

       新建一個ASP.NET MVC4應用程序,結構如下圖所示:


對各個文件夾的說明:

(1)App_Data 文件夾用於存儲應用程序數據。   

(2)Content 文件夾用於存放靜態文件,比如樣式表(CSS 文件)、圖標和圖像。 

(3)Controllers 文件夾包含負責處理用戶輸入和相應的控制器類。

(4)Models 文件夾包含表示應用程序模型的類。模型控制並操作應用程序的數據。

(5)Views 文件夾用於存儲與應用程序的顯示相關的 HTML 文件(用戶界面)。

(6)Scripts 文件夾存儲應用程序的 JavaScript 文件。

 下面就主要的Controller、Model和View做出說明。

一、控制器

1、描述

       控制器(Controller)主要負責響應用戶的輸入,並在響應時修改模型(Model)。通過這種方式,控制器主要關注的是應用程序流、輸入數據的處理,以及對相關視圖(View)輸出數據的提供。

2、簡單控制器

       新建一個ASP.NET MVC4應用程序,會自動生成一個HomeController和AccountController。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
            return View();
        }
    }
}

  

      直接按F5運行程序即可看到index試圖中的內容,此時瀏覽器的URL為:

       http://localhost:4573,或者修改瀏覽器地址為:

       http://localhost:4573/home

       http://localhost:4573/home/index

       程序默認會托管在VS2013自帶的IIS中,采用的端口號為4573。如果程序托管在MyWeb.com中,則URL應為:

       http://MyWeb.com/home/index。

3、控制器操作中的參數

       前面的例子Action中返回的是字符串常量,下面就讓它們通過相應URL傳進來的參數動態地執行操作。

       在這里,我們使用HttpUtility.HtmlEncode來預處理用戶輸入。這樣就能阻止用戶用鏈接向視圖中注入JavaScriptd代碼或HTML標記,比如/home/sayhello?content=<script>window.location='http://www.baidu.com'</script>。


 
public string SayHello(string content)
{
    string message = HttpUtility.HtmlEncode("Hello " + content);
    return message;
}

 

  1.  
  2. public string Details(int Id)
    {
        return "ID:" + Id;
    }

     

4、路由---將URL映射到動作

       框架是如何知道將URL映射到一個特定的控制動作的?答案就在Global.asax文件的RegisterRoutes方法中。該方法定義了將一個URL模式映射到控制器或動作的路由。

using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace MvcApplication1
{
    // 注意: 有關啟用 IIS6 或 IIS7 經典模式的說明,
    // 請訪問 http://go.microsoft.com/?LinkId=9394801
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }
    }
}

 

  1. 在RegisterRoutes方法上按F12,轉到該方法的定義,如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;  
 
namespace MvcApplication1
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                                name: "Default",
                                url: "{controller}/{action}/{id}",
                                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                            );
        }
    }
}

   

5、控制器總結

(1)不需要做任何配置,只需瀏覽到/控制器/動作URL即可;

(2)控制器是一個非常簡單的類,繼承自System.Web.Mvc.Controller類;

(3)用控制器在瀏覽器中顯示文本,沒有用到View或Model。

二、視圖

1、作用

       提供用戶界面。一個控制器可以對應多個試圖,一個視圖可以被多個控制器使用。

       在Action名上右鍵→添加試圖→View1。

2、指定視圖

@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>View1</title>
</head>
<body>
    <div>
        <h2>@ViewBag.Message</h2>
    </div>
</body>
</html>

3、ViewData和ViewBag的區別於聯系

       在前面的例子中,使用了ViewBag的Message屬性從控制器往視圖傳遞數據,ViewData是一個特殊的字典類,可以按標准語法進行使用:ViewData["CurrentTime"]=DateTime.Now;

       這種語法也可以用動態封裝器ViewBag:ViewBag.CurrentTime=DateTime.Now;

注意:

(1)盡管只有當要訪問的關鍵字是有效的C#標識符是,ViewBag才起作用,如在ViewData["Key With Spaces"]就不能使用ViewBag訪問,編譯不通過;

(2)動態值不能作為一個參數傳遞給擴展方法。因為C#編譯器為了選擇正確的擴展方法,在編譯是必須知道每個參數真正類型。如:@Html.TextBox("name",ViewBag.Name)不會編譯通過,可以改為:

       ①@Html.TextBox("name",ViewData["Name"])

       ②@Html.TextBox("name",(string)ViewBag.Name)

4、強類型視圖

       現在需要編寫一個顯示Album實例列表的視圖。一簡單的方法就是通過ViewBag屬性把那些Album實例添加到視圖數據字典中,然后在視圖中迭代他們。

(1)首先,在Models文件夾下新建一個Album類,為了簡單起見,只定義一個Title屬性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{
    public class Album
    {
        public string Title { get; set; }
    }
}
  1. (2)控制器
public ActionResult List()
{
    var album = new List<Album>();
    for (int i = 0; i < 10; i++)
    {
        album.Add(new Album { Title = "Product " + i.ToString() });
    }
    //一、使用ViewBag傳值
    //ViewBag.Album = album;
    //return View("ListView");
    //二、使用ViewData傳值
    ViewData["Album"] = album;
    return View("ListView");
}

  

(3)視圖

       在List上右鍵→添加視圖。

@{
    Layout = null;
}
<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @*一、使用ViewBag傳值*@
            @*@foreach(MvcApplication1.Models.Album a in (ViewBag.Album as IEnumerable
            <MvcApplication1.Models.Album>))
            {
                <li>@a.Title</li>
            }*@
            @*二、使用ViewBag傳值*@

            @foreach (MvcApplication1.Models.Album a in (ViewData["Album"] as IEnumerable<MvcApplication1.Models.Album>))
            {
                <li>@a.Title</li>
            }

        </ul>
        <pre name="code" class="html">
        <ul>
            @foreach(dynamic d in ViewBag.Album)
            {
                <li>@d.Title</li>
            }
 
        </ul>
    </div>
</body>
</html>

運行效果:

 
        
       注意,在枚舉之前需要動態的將ViewBag.Album轉換為IEnumerable<Album>類型,為了使代碼干凈整潔,也可以使用dynamic關鍵字。
<ul>
    @foreach (dynamic d in ViewBag.Album)
    {
        <li>@d.Title</li>
    }
</ul> 

       請記住,ViewData是ViewDataDictionary類型的,它有一個額外的Model屬性,可以用來在視圖中獲取指定的模型對象。由於在ViewData中只能傳遞一個模型對象,因此,我們利用這一點可以很容易的實現向視圖傳遞一個特定的類對象。

       在Controller方法中,可以通過重載的List方法中傳遞模型實例來指定模型,代碼如下:

public ActionResult List()
{
    var album = new List<Album>();
    for (int i=0;i < 10; i++) 
    {
        album.Add(new Album { Title="Product " + i.ToString() });
    }
    ViewData["Album"]=album;
    return View("ListView",album);
}

@model IEnumerable<MvcApplication1.Models.Album>

@{
    Layout = null;
}

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @foreach(dynamic d in Model)
            {
                <li>@d.Title</li>
            }
        </ul>
    </div>
</body>
</html>

       如果不想輸入模型類型的完全限定類型名,可使用using關鍵字聲明,如下所示:

 

@using MvcApplication1.Models

@model IEnumerable<Album>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @foreach (dynamic d in Model)
            {
                <li>@d.Title</li>
            }
        </ul>
    </div>
</body>
</html>

       對於在視圖中經常使用的名稱空間,一個較好的方法就是在Views目錄下的web.config文件中聲明。

 

<system.web.webPages.razor>
    <host factoryType = "System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    < pages pageBaseType="System.Web.Mvc.WebViewPage">
        <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization"/>
        <add namespace="System.Web.Routing" />
        <add namespace="MvcApplication1.Models"/>
        </namespaces>
    </pages>
</system.web.webPages.razor>
 

5、Razor視圖引擎

5.1 先來看一個簡單的例子。

@{
    Layout = null;
}

@{
    var items = new string[] { "one", "two", "three" };
}

<!DOCTYPE html>
<html>
<head>
    <title>ListView</title>
</head>

<body>
    <div>
        <ul>
            @foreach (var item in items)
            {
                <li>@item</li>
            }
        </ul>
    </div>
</body>
</html>

 

5.2 Html編碼

       因為在很多情況下需要用視圖顯示用戶輸入,如博客評論等,所以總是存在着潛在的跨站腳本注入攻擊(也成XSS),值得稱贊的是,Razor表達式是Html自動編碼的,如下不會彈出一個警示框,而是直接顯示html代碼。

 

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

 

        然而,如果想要展示Html標簽,就要返回一個System.Web.IHtml對象的實例,Razor並不對它進行編碼。當然也可以創建一個HtmlStringl實例或者使用Html.Raw便捷方法。

 

@{

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

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

  

  1. 效果:

 

 

       雖然這種自動的HTML編碼通過對一HTML形式顯示的用戶輸入進行編碼能有效的緩和XSS的脆弱性,但是對於在JavaScript中時遠遠不夠的。例如:

 

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

    });
</script>

 

  1.        當在JavaScript中將用戶提供的值賦給變量時,要使用JavaScript字符串編碼而不僅僅是HTML編碼,記住這一點是很重要的,也就是要用@Ajax.JavaScriptStringEncode方法對用戶輸入進行編碼。

5.3 布局

       Razor的布局有助於使用應用程序中的多個視圖保持一致的外觀,可使用布局為網站定義公共模板(或只是其中的一部分),公共模板包含一個或多個占位符,應用程序中的其他視圖為他們提供內容。

       下面看一個非常簡單的布局,新建一個名稱為MyLayout.cshtml的視圖,由於要作為公共模板,所以將其放在/Views/Shared/路徑下。

 

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>
<body>
    <h1>@ViewBag.Title</h1>
    <div id="Container">@RenderBody()</div>
</body>
</html>

 

 

 

  1.        其中的@RenderBody()稱為占位符,用來標記使用這個模板的視圖將渲染他們的主要內容的位置。

 

       接下來新建一個視圖,將使用其作為模板。

 

@{
    Layout = "~/Views/Shared/MyLayout.cshtml";
    ViewBag.Title = "GoodLuck";
}
<p>This is the main content</p>

 

 

 

 

  1. 運行效果如下:

       布局可能有多個節,例如下面示例在前面的布局基礎上添加了一個頁腳節:

 

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>
<body>
    <h1>@ViewBag.Title</h1>
    <div id="Container">@RenderBody()</div>
    <footer>@RenderSection("Footer")</footer>
</body>
</html>

 

 

 

 

  1.        在不做任何改變的情況下再次運行前面的視圖,將會拋出一個異常,提示沒有定義的Footer節。

 

       默認情況下,視圖必須為布局中定義的沒一個節提供相應的內容。更新后的View1視圖如下所示:

 

@{
    Layout = "~/Views/Shared/MyLayout.cshtml";
    ViewBag.Title = "GoodLuck";
}

<p>This is the main content</p>

@section Footer{
    This is the <strong>footer</strong>.
}

 

 

 

  1.  

       RenderSection方法有一個重載的版本,允許在布局中指定不需要的節,可以給required參數傳遞一個false值來標記Footer節是可選的:

 

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>

<body>
    <h1>@ViewBag.Title</h1>
    <div id="Container">@RenderBody()</div>
    <footer>@RenderSection("Footer", required: false)</footer>
</body>
</html>

 

 

 

 



5.4 ViewStart

       在前面的例子中,每一個視圖都是用Layout屬性來指定它的布局,如果多個視圖使用同一個布局,就會產生冗余,並且很難維護。

       _ViewStart.cshtml頁面可用來消除這種冗余,這個文件的代碼先於同目錄下任何視圖代碼的執行,這個文件也可以遞歸地應用到子目錄下的任何視圖。

@{

Layout="~/Views/Shared/_Layout.cshtml";

}

       因為這個代碼先於任何視圖執行,所以一個視圖可以重寫Layout屬性的默認值,從而重新選擇一個不同的布局。

5.4 指定部分視圖

       除了返回視圖之外,操作方法也可以通過PartialView方法以PartialResult的形式返回部分視圖。

The end

ASP.NET MVC 是微軟官方提供的以MVC模式為基礎的ASP.NET Web應用程序(Web Application)框架,它由Castle的MonoRail而來。

MVC 編程模式

       MVC 是三種 ASP.NET 編程模式中的一種。

       MVC 是一種使用 MVC(Model View Controller 模型-視圖-控制器)設計創建 Web 應用程序的模式。

    (1)Model(模型)表示應用程序核心(比如數據庫記錄列表)。

    (2)View(視圖)顯示數據(數據庫記錄)。

    (3)Controller(控制器)處理輸入(寫入數據庫記錄)。

       MVC 模式同時提供了對 HTML、CSS 和 JavaScript 的完全控制。Model(模型)是應用程序中用於處理應用程序數據邏輯的部分。通常模型對象負責在數據庫中存取數據。View(視圖)是應用程序中處理數據顯示的部分。通常視圖是依據模型數據創建的。Controller(控制器)是應用程序中處理用戶交互的部分。通常控制器負責從視圖讀取數據,控制用戶輸入,並向模型發送數據。       

       新建一個ASP.NET MVC4應用程序,結構如下圖所示:


對各個文件夾的說明:

(1)App_Data 文件夾用於存儲應用程序數據。   

(2)Content 文件夾用於存放靜態文件,比如樣式表(CSS 文件)、圖標和圖像。 

(3)Controllers 文件夾包含負責處理用戶輸入和相應的控制器類。

(4)Models 文件夾包含表示應用程序模型的類。模型控制並操作應用程序的數據。

(5)Views 文件夾用於存儲與應用程序的顯示相關的 HTML 文件(用戶界面)。

(6)Scripts 文件夾存儲應用程序的 JavaScript 文件。

 下面就主要的Controller、Model和View做出說明。

一、控制器

1、描述

       控制器(Controller)主要負責響應用戶的輸入,並在響應時修改模型(Model)。通過這種方式,控制器主要關注的是應用程序流、輸入數據的處理,以及對相關視圖(View)輸出數據的提供。

2、簡單控制器

       新建一個ASP.NET MVC4應用程序,會自動生成一個HomeController和AccountController。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
            return View();
        }
    }
}

 



       直接按F5運行程序即可看到index試圖中的內容,此時瀏覽器的URL為:

 

       http://localhost:4573,或者修改瀏覽器地址為:

       http://localhost:4573/home

       http://localhost:4573/home/index

       程序默認會托管在VS2013自帶的IIS中,采用的端口號為4573。如果程序托管在MyWeb.com中,則URL應為:

       http://MyWeb.com/home/index。

3、控制器操作中的參數

       前面的例子Action中返回的是字符串常量,下面就讓它們通過相應URL傳進來的參數動態地執行操作。

       在這里,我們使用HttpUtility.HtmlEncode來預處理用戶輸入。這樣就能阻止用戶用鏈接向視圖中注入JavaScriptd代碼或HTML標記,比如/home/sayhello?content=<script>window.location='http://www.baidu.com'</script>。


 

public string SayHello(string content)
{
    string message = HttpUtility.HtmlEncode("Hello " + content);
    return message;
}

 

 

 



public string Details(int Id)
{
    return "ID:" + Id;
}

 


 

 

4、路由---將URL映射到動作

       框架是如何知道將URL映射到一個特定的控制動作的?答案就在Global.asax文件的RegisterRoutes方法中。該方法定義了將一個URL模式映射到控制器或動作的路由。

 

using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace MvcApplication1
{
    // 注意: 有關啟用 IIS6 或 IIS7 經典模式的說明,
    // 請訪問 http://go.microsoft.com/?LinkId=9394801
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }
    }
}

 

 

 



在RegisterRoutes方法上按F12,轉到該方法的定義,如下:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplication1
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                                name: "Default",
                                url: "{controller}/{action}/{id}",
                                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
                            );
        }
    }
}

 

 

 



5、控制器總結

 

(1)不需要做任何配置,只需瀏覽到/控制器/動作URL即可;

(2)控制器是一個非常簡單的類,繼承自System.Web.Mvc.Controller類;

(3)用控制器在瀏覽器中顯示文本,沒有用到View或Model。

二、視圖

1、作用

       提供用戶界面。一個控制器可以對應多個試圖,一個視圖可以被多個控制器使用。

       在Action名上右鍵→添加試圖→View1。

2、指定視圖

 

@{
     Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>View1</title>
</head>
<body>
    <div>
        <h2>@ViewBag.Message</h2>
    </div>
</body>
</html>

 

 

 



3、ViewData和ViewBag的區別於聯系

       在前面的例子中,使用了ViewBag的Message屬性從控制器往視圖傳遞數據,ViewData是一個特殊的字典類,可以按標准語法進行使用:ViewData["CurrentTime"]=DateTime.Now;

       這種語法也可以用動態封裝器ViewBag:ViewBag.CurrentTime=DateTime.Now;

注意:

(1)盡管只有當要訪問的關鍵字是有效的C#標識符是,ViewBag才起作用,如在ViewData["Key With Spaces"]就不能使用ViewBag訪問,編譯不通過;

(2)動態值不能作為一個參數傳遞給擴展方法。因為C#編譯器為了選擇正確的擴展方法,在編譯是必須知道每個參數真正類型。如:@Html.TextBox("name",ViewBag.Name)不會編譯通過,可以改為:

       ①@Html.TextBox("name",ViewData["Name"])

       ②@Html.TextBox("name",(string)ViewBag.Name)

4、強類型視圖

       現在需要編寫一個顯示Album實例列表的視圖。一簡單的方法就是通過ViewBag屬性把那些Album實例添加到視圖數據字典中,然后在視圖中迭代他們。

(1)首先,在Models文件夾下新建一個Album類,為了簡單起見,只定義一個Title屬性。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplication1.Models
{
    public class Album
    {
        public string Title { get; set; }
    }
}

 

 

 



(2)控制器

 

public ActionResult List()
{
    var album = new List<Album>();
    for (int i=0;i < 10 ;i++) 
    {
        album.Add(new Album { Title="Product " + i.ToString() });
    }

    //一、使用ViewBag傳值
    //ViewBag.Album = album;
    //return View("ListView");

    //二、使用ViewData傳值
    ViewData["Album"] = album;
    return View("ListView");
}

 

 

 



(3)視圖

       在List上右鍵→添加視圖。

 

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @*一、使用ViewBag傳值*@
            @*@foreach(MvcApplication1.Models.Album a in (ViewBag.Album as IEnumerable<MvcApplication1.Models.Album>))
            {
                <li>@a.Title</li>
            }*@

            @*二、使用ViewBag傳值*@
            @foreach (MvcApplication1.Models.Album a in (ViewData["Album"] as IEnumerable<MvcApplication1.Models.Album>))
            {
                <li>@a.Title</li>
            }
        </ul>

        <pre name="code" class="html">

        <ul>
            @foreach(dynamic d in ViewBag.Album)
            {
                <li>@d.Title</li>
            }
        </ul>
    </div>
</body>
</html>

 

 

 



運行效果:

 

 
        
       注意,在枚舉之前需要動態的將ViewBag.Album轉換為IEnumerable<Album>類型,為了使代碼干凈整潔,也可以使用dynamic關鍵字。
<ul>
    @foreach (dynamic d in ViewBag.Album)
    {
        <li>@d.Title</li>
    }
</ul>

 



       請記住,ViewData是ViewDataDictionary類型的,它有一個額外的Model屬性,可以用來在視圖中獲取指定的模型對象。由於在ViewData中只能傳遞一個模型對象,因此,我們利用這一點可以很容易的實現向視圖傳遞一個特定的類對象。

       在Controller方法中,可以通過重載的List方法中傳遞模型實例來指定模型,代碼如下:

 

public ActionResult List()
{
    var album = new List<Album>();
    for (int i=0;i < 10;i++) 
    {
        album.Add(new Album { Title="Product " + i.ToString() });
    }
    ViewData["Album"]=album;
    return View("ListView",album);
}

@model IEnumerable<MvcApplication1.Models.Album>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @foreach(dynamic d in Model)
            {
                <li>@d.Title</li>
            }
        </ul>
    </div>
</body>
</html>

 

 

 



       如果不想輸入模型類型的完全限定類型名,可使用using關鍵字聲明,如下所示:

 

@using MvcApplication1.Models
@model IEnumerable<Album>

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @foreach (dynamic d in Model)
            {
                <li>@d.Title</li>
            }
        </ul>
    </div>
</body>
</html>

 

 

 



       對於在視圖中經常使用的名稱空間,一個較好的方法就是在Views目錄下的web.config文件中聲明。

 

<system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
        <namespaces>
            <add namespace="System.Web.Mvc" />
            <add namespace="System.Web.Mvc.Ajax" />
            <add namespace="System.Web.Mvc.Html" />
            <add namespace="System.Web.Optimization" />
            <add namespace="System.Web.Routing" />
            <add namespace="MvcApplication1.Models" />
        </namespaces>
    </pages>
</system.web.webPages.razor>

 

 

 



5、Razor視圖引擎

5.1 先來看一個簡單的例子。

 

@{
    Layout = null;
}

@{
    var items = new string[] { "one", "two", "three" };
}
<!DOCTYPE html>

<html>
<head>
    <title>ListView</title>
</head>
<body>
    <div>
        <ul>
            @foreach (var item in items)
            {
                <li>@item</li>
            }
        </ul>
    </div>
</body>
</html>

 

 

 



5.2 Html編碼

       因為在很多情況下需要用視圖顯示用戶輸入,如博客評論等,所以總是存在着潛在的跨站腳本注入攻擊(也成XSS),值得稱贊的是,Razor表達式是Html自動編碼的,如下不會彈出一個警示框,而是直接顯示html代碼。

 

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

<span>@message</span>

 

 

 



       然而,如果想要展示Html標簽,就要返回一個System.Web.IHtml對象的實例,Razor並不對它進行編碼。當然也可以創建一個HtmlStringl實例或者使用Html.Raw便捷方法。

 

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

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

 

 

 

  1. 效果:

 

 

       雖然這種自動的HTML編碼通過對一HTML形式顯示的用戶輸入進行編碼能有效的緩和XSS的脆弱性,但是對於在JavaScript中時遠遠不夠的。例如:

 

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

 

 

 

       當在JavaScript中將用戶提供的值賦給變量時,要使用JavaScript字符串編碼而不僅僅是HTML編碼,記住這一點是很重要的,也就是要用@Ajax.JavaScriptStringEncode方法對用戶輸入進行編碼。

5.3 布局

       Razor的布局有助於使用應用程序中的多個視圖保持一致的外觀,可使用布局為網站定義公共模板(或只是其中的一部分),公共模板包含一個或多個占位符,應用程序中的其他視圖為他們提供內容。

       下面看一個非常簡單的布局,新建一個名稱為MyLayout.cshtml的視圖,由於要作為公共模板,所以將其放在/Views/Shared/路徑下。

 

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>
<body>
    <h1>@ViewBag.Title</h1>
    <div id="Container">@RenderBody()</div>
</body>
</html>

 

 

 

  1.        其中的@RenderBody()稱為占位符,用來標記使用這個模板的視圖將渲染他們的主要內容的位置。

 

       接下來新建一個視圖,將使用其作為模板。

 

@{
    Layout = "~/Views/Shared/MyLayout.cshtml";
    ViewBag.Title = "GoodLuck";
}

<p>This is the main content</p>

 

 

 

運行效果如下:

       布局可能有多個節,例如下面示例在前面的布局基礎上添加了一個頁腳節:

 

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>

<body>
    <h1>@ViewBag.Title</h1>
    <div id="Container">@RenderBody()</div>
    <footer>@RenderSection("Footer")</footer>
</body>
</html>

 

 

 

 

  1.        在不做任何改變的情況下再次運行前面的視圖,將會拋出一個異常,提示沒有定義的Footer節。

 

       默認情況下,視圖必須為布局中定義的沒一個節提供相應的內容。更新后的View1視圖如下所示:

 

@{
    Layout = "~/Views/Shared/MyLayout.cshtml";
    ViewBag.Title = "GoodLuck";
}

    <p>This is the main content</p>
    @section Footer{
    This is the <strong>footer</strong>
}

 

 

 

 

       RenderSection方法有一個重載的版本,允許在布局中指定不需要的節,可以給required參數傳遞一個false值來標記Footer節是可選的:

 

<!DOCTYPE html>
<html>
<head>
    <title>@ViewBag.Title</title>
</head>
<body>
    <h1>@ViewBag.Title</h1>
    <div id="Container">@RenderBody()</div>
    <footer>@RenderSection("Footer", required: false)</footer>

</body>
</html>

 

5.4 ViewStart

       在前面的例子中,每一個視圖都是用Layout屬性來指定它的布局,如果多個視圖使用同一個布局,就會產生冗余,並且很難維護。

       _ViewStart.cshtml頁面可用來消除這種冗余,這個文件的代碼先於同目錄下任何視圖代碼的執行,這個文件也可以遞歸地應用到子目錄下的任何視圖。

@{

Layout="~/Views/Shared/_Layout.cshtml";

}

       因為這個代碼先於任何視圖執行,所以一個視圖可以重寫Layout屬性的默認值,從而重新選擇一個不同的布局。

5.4 指定部分視圖

       除了返回視圖之外,操作方法也可以通過PartialView方法以PartialResult的形式返回部分視圖。

The end

 


免責聲明!

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



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