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. 关于vue的数据增删的一些细节

    第一种情况:在vue中使用的数据必须先在data中定义数据,不然报错: 第二种情况:访问对象中不存在的值,是可以得到undefined,但是不会报错 第三种:vue只会监听data已经定义的值,后续添 ...

  2. 【错误解决】Intellj(IDEA) warning no artifacts configured

    : warning no artifacts configured,,上面木有Artifacts的选项,,好尴尬, [解决方案]artifacts,是maven中的概念(项目是maven项目),由于没 ...

  3. Java中的线程协作之Condition

    一.Condition接口 1.Condition接口的常用方法介绍 /** * 已经获取到锁的线程调用该方法会进入等待状态,知道其他持有锁的线程通知(signal)等待队列中的线程或者被中断退出等待 ...

  4. 手动编译安装nginx

    1.下载nginx源码包并解压 可在http://nginx.org/en/download.html下载.tar.gz的源码包,如(nginx-1.4.7.tar.gz) 下载后通过tar -xvz ...

  5. [Swift]LeetCode227. 基本计算器 II | Basic Calculator II

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  6. [Swift]LeetCode286. 墙和门 $ Walls and Gates

    You are given a m x n 2D grid initialized with these three possible values. -1 - A wall or an obstac ...

  7. [Swift]LeetCode310. 最小高度树 | Minimum Height Trees

    For an undirected graph with tree characteristics, we can choose any node as the root. The result gr ...

  8. [Swift]LeetCode383. 赎金信 | Ransom Note

    Given an arbitrary ransom note string and another string containing letters from all the magazines, ...

  9. [Swift]LeetCode513. 找树左下角的值 | Find Bottom Left Tree Value

    Given a binary tree, find the leftmost value in the last row of the tree. Example 1: Input: 2 / \ 1 ...

  10. python之Django学习笔记(三)---URL调度/URL路由

    在django中,用户发起url请求消息首先到工程的urls.py中查找是否有匹配的url路径 刚创建好的工程中urls.py只有下面几行代码: from django.contrib import ...