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; }
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(); } } }
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; } } }
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>
運行效果:
<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>
雖然這種自動的HTML編碼通過對一HTML形式顯示的用戶輸入進行編碼能有效的緩和XSS的脆弱性,但是對於在JavaScript中時遠遠不夠的。例如:
<script type="text/javascript"> $(function () { var message = 'Hello @Ajax.JavaScriptStringEncode(ViewBag.Message)'; $("#message").html(message).show('slow'); }); </script>
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>
接下來新建一個視圖,將使用其作為模板。
@{ 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>
默認情況下,視圖必須為布局中定義的沒一個節提供相應的內容。更新后的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
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>
運行效果:
<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>
雖然這種自動的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>
接下來新建一個視圖,將使用其作為模板。
@{ 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>
默認情況下,視圖必須為布局中定義的沒一個節提供相應的內容。更新后的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
