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 = ; i < ; 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=;i < ; 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>.
}

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=;i < ;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=;i < ;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

菜鸟学ASP.NET MVC4入门笔记的更多相关文章

  1. 数迹学——Asp.Net MVC4入门指南(2):添加一个控制器

    自嘲一下......万事还是得从官方的入门开始 由于找不到适合新新手的MVC入门实例所以回过头来做一下微软的 <Asp.Net MVC4入门指南>. 只有把自己放在太阳下暴晒,才知道自己有 ...

  2. 数迹学——Asp.Net MVC4入门指南(5):从控制器访问数据模型

    MovieController中的方法Index()代码,初认识,应该有很多理解错误的地方,暂时这么记忆吧,待随后修改 Index()代码: @model IEnumerable<MVCMovi ...

  3. 数迹学——Asp.Net MVC4入门指南(4):添加一个模型

    一.添加模型类 二.添加MovieDBContext类,连接数据库 DbContext类继承自 System.Data.Entity; 负责在数据库中获取,存储,更新,处理实例 MovieDBCont ...

  4. 数迹学——Asp.Net MVC4入门指南(3):添加一个视图

    方法返回值  ActionResult(方法执行后的结果) 例子1 public ActionResult methordName() { return "string"; } 例 ...

  5. 【翻译转载】【官方教程】Asp.Net MVC4入门指南(2):添加一个控制器

    2. 添加一个控制器 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-c ...

  6. 【部分补充】【翻译转载】【官方教程】Asp.Net MVC4入门指南(4):添加一个模型

    4. 添加一个模型 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-mo ...

  7. 【翻译转载】【官方教程】Asp.Net MVC4入门指南(3):添加一个视图

    3. 添加一个视图 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/adding-a-vi ...

  8. 【翻译转载】【官方教程】Asp.Net MVC4入门指南(1): 入门介绍

    1. Asp.Net MVC4 入门介绍 · 原文地址:http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/ ...

  9. ASP.NET MVC4入门到精通系列目录汇总

    序言 最近公司在招.NET程序员,我发现好多来公司面试的.NET程序员居然都没有 ASP.NET MVC项目经验,其中包括一些工作4.5年了,甚至8年10年的,许多人给我的感觉是:工作了4.5年,We ...

随机推荐

  1. win10企业版永久激活方法

    步骤: 1.右键点击桌面左下角"windows"图标,点击打开“命令提示符” 2.复制命令:slmgr.vbs /upk,按回车确定,弹出窗口显示“成功地卸载了产品密钥” 3.复制 ...

  2. CF F. Shovels Shop(前缀和预处理+贪心+dp)

    F. Shovels Shop time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  3. spring的配置和使用

    spring的配置和使用 1. 创建基于java的配置. 配置极少量的XML来启用java配置:   <?xml version="1.0" encoding="U ...

  4. SpringBoot项目的创建流程(初步)

    小伙伴们在学习的过程中大概也发现了这两个框架需要我们手动配置的地方非常多,不过做JavaEE开发的小伙伴们肯定也听说过“约定大于配置”这样一句话,就是说系统,类库,框架应该假定合理的默认值,而非要求提 ...

  5. Ubuntu 16.04下安装搜狗输入法

    在确保更新了国内镜像源的前提下: 安装sogou输入法步骤 一.安装fcitx键盘输入法系统(系统已安装的可忽略此步骤) 1.添加以下源 sudo add-apt-repository ppa:fci ...

  6. 1.4 The usage of plug-in

    Once upon a time, we once thought naively that Android plug-in was intended to add new features or a ...

  7. [Swift]LeetCode539. 最小时间差 | Minimum Time Difference

    Given a list of 24-hour clock time points in "Hour:Minutes" format, find the minimum minut ...

  8. [Swift]LeetCode712. 两个字符串的最小ASCII删除和 | Minimum ASCII Delete Sum for Two Strings

    Given two strings s1, s2, find the lowest ASCII sum of deleted characters to make two strings equal. ...

  9. BBS论坛(二十八)

    28.1.帖子分页功能完成 (1)manage.py 通过命令生成100个帖子,用于测试 @manager.command def create_test_post(): for x in range ...

  10. 查询运营商的ip段

    查询运营商的ip段 所有的IP地址都是通过国际组织NIC(Network Information Center)统一分配的,目前世界上有三个这样的网络信息中心: InterNic: 负责美国及其他地区 ...