ASP.NET MVC3 系列教程 – 新的Layout布局系统

原文地址:http://www.cnblogs.com/highend/archive/2011/04/18/asp_net_mvc3_layout.html

I:回忆MVC2当中MasterPage那些事

code:

<!------------Begin-------------->
<!-- Master文件 -->
<%@ Master Language="C#"
Inherits="System.Web.Mvc.ViewMasterPage" %>
Master head
<asp:ContentPlaceHolder ID="MainContent" runat="server" />
Master1...
<asp:ContentPlaceHolder ID="OtherContent" runat="server" />
Master2...
<asp:ContentPlaceHolder ID="AnyContent" runat="server" />
Master3...
<!-------------End--------------->

<!------------Begin-------------->
<!-- 某个View文件 -->
<%@ Page Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
MainContent...
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="OtherContent" runat="server">
OtherContent...
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="AnyContent" runat="server">
AnyContent...
</asp:Content>
<!-------------End--------------->

<!------------Begin-------------->
<!-- 最后传回给客户端的文件 -->
Master head
MainContent...
Master1...
OtherContent...
Master2...
AnyContent...
Master3...
<!-------------End--------------->

我们可以看到在Master中ContentPlaceHolder服务端控件起到了一个占位符的作用.最后输出的,其实是在View当中的Content服务端控件内的内容,接下来开始介绍Layout.

II:ASP.NET MVC3 新的Layout布局系统

在MVC3当中我们可以利用新的Layout布局系统来代替掉原来在MVC2当中使用的MasterPage(当然在MVC3当中,如果你是继续使用ASPX视图引擎的话,那么还是可以用回原来的MasterPage,然后~~~~然后~你会和runat=”server”保持着从.NET
1.x到.NET 4.0以来从没有间断过的合作关系,可谓缘分呀!).

我们在VS2010 MVC3项目中创建Item时,从创建向导中可以看到以下新增的几个Item

下面进行逐一介绍:

Layout页:
该家伙其实就相当于原来的Master文件.为站点的统一主题界面和减少大部分冗余的Html,head,body标记曾作出过很大的贡献.可谓是功不可莫啊!MasterPage他的诞生是在.NET
2.0版本!在服役到.NET4.0版本后出现了一个新成员[Layout]去向他挑战.MasterPage能否经得起新成员的挑战呢?这个还是得留各位观众做详细对比吧!

Partial页:
相当于原来的UserControl.它可以为你减轻不少需要重复劳动的时间!

View页:
就是View啦.创建它时.一般都是在不需要使用Layout/MasterPage的时候.

View Page with Layout:
等同于原来的View Content
Page.它的功能只是为了实现原来在Layout/MasterPage下所定义的占位符.当然在原来的MasterPage中如果你没有实现原先定义的占位符<asp:ContentPlaceHolder
/>,那么在最终合并输出的时候MasterPage占位符<asp:ContentPlaceHolder />那里就会输出空.

以上这4个新成员都是可以利用新的Razor视图引擎进行工作.如果你还没了解Razor那么可以参考我的另外一编文章

1.Layout页基础:
如果你有使用MasterPage的经验,你将会记得如下的几个东西

A:<%@ Master %>

B:<%@ Page %>

C:<asp:ContentPlaceHolder />

D:<asp:Content />

但是在Layout中,以上的这些东西将会消失.(作者不排除有WebPages和WebForms兼容工作的可能性)

取而代之的新功能是:

A.Layout属性:等同于原来的MasterPageFile属性.

[email protected]()方法:直接渲染整个View到占位符处,而不需要原来所使用的<asp:Content />.

[email protected]()方法:渲染指定的页面到占位符处.

[email protected]方法:声明一个占位符,和原来的<asp:ContentPlaceHolder />功能类似.

[email protected]标记:对@RenderSection方法声明的占位符进行实现,和原来的<asp:Content />功能类似.

[email protected]()方法的使用

首先在~/Views/Shared/下创建一个名为_MyLayout.cshtml的LayoutPage文件,并将默认的内容替换为如下:

<!DOCTYPE html>

<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<div>
开始渲染Body<br />
@RenderBody()
渲染Body结束<br />
</div>
</body>
</html>

然后打开在~/Views/Home/Index.cshtml文件并替换为如下的内容:

@{
ViewBag.Title = "首页";
}

<div>
这里就是渲染Body啦.~~不需要写神马&lt;asp:Content /&gt;,其实因为RenderBody()不在有歧义.
</div>

最后输出截图为:
 

这个与之前MasterPage的代码量相比之下减少了许多,而更为简洁明了.

最后别忘记把~/Views/_ViewStart.cshtml中的Layout属性改为:

Layout = "~/Views/Shared/_MyLayout.cshtml";喔.

在此,你或许会有疑问了.在_Layout中定义的RenderBody()是Render那个页啊?

答:其实最后Render页的归属就是Render你所访问的那个页,比如你访问/Home/Index.那么Render就是Home控制器下的Index.cshtml这个文件,
如果访问的是/Ohter/SomePage时,那么Render的是Ohter控制器下的SomePage这个.cshtml!

在这里可能有的朋友没有接触过MVC.在此补个基础,在默认的路由设置选项下:

public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);

}

请求地址:http://localhost/Home/Index的工作流程为下图(这里没有考虑Layout):

如果这个RenderBody满足不了你的业务需求,请放心,在此介绍另外一个Render方式RenderPage().它可以让你指定要Render的页.

[email protected]()方法的使用

在~/Views/Home/文件夹下新建立一个ViewPage1.cshtml文件,将内容改为如下:

<div>
这里是~/Views/Home/ViewPage1.cshtml,老规矩:还是不用写&lt;asp:Content /&gt;
</div>

并在原来的_MyLayout.cshtml文件中增加几行代码变成下面的这个样子:

<!DOCTYPE html>

<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<div>
开始渲染Body<br />
@RenderBody()
渲染Body结束<br />
<br />
开始渲染其他页<br />
@RenderPage("~/Views/Home/ViewPage1.cshtml")
渲染其他页结束<br />

</div>
</body>
</html>

我们来看最终的输出效果:

在这里记住:@RenderBody()只能在_Layout.cshtml中使用一次,而@RenderPage()则可以使用多次!

好了在这里如果还有不明白的朋友们.我下面上个图说明Render的工作原理

如果想要了解在Layout中如何使用类似于原来MasterPage中的<asp:ContentPlaceHolder
/><asp:Content />功能请继续往下看.

III:在Layout布局系统中实现类似于原来MasterPage功能的实现方式

好,写到这里开始介绍上一章节中没有介绍完的两个东西:@RenderSection方法和@section标记
[email protected]()方法等价于<asp:ContentPlaceHolder
/>,用途为在Layout中声明一个占位符.
操作:在原来的_MyLayout.cshtml文件中更改内容为如下:

@{
//some code
}
<!DOCTYPE html>

<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<div>
开始渲染Body<br />
@RenderBody()
渲染Body结束<br />
<br />
开始渲染其他页<br />
@RenderPage("~/Views/Home/ViewPage1.cshtml")
渲染其他页结束<br />
<br />
HOHO,开始学习Section了<br />
开始渲染Section<br />
声明方式1(推荐):SectionA:<br />
@RenderSection("SectionA", false)
-------<br />

声明方式2:SectionB:<br />
@{
if (IsSectionDefined("SectionB"))
{
@RenderSection("SectionB")
}
}
-------<br />
渲染Sction结束<br />
</div>
</body>
</html>

在~/Views/Home/Index.cshtml中更改为如下内容:

@{
ViewBag.Title = "首页";

//
// some code
//
}

@section SectionA{
<div>这里是SectionA:也不需要写神马runat="server"啊,有木有</div>
}

@section SectionB{
<div>这里是SectionB:也不需要写神马&lt;asp:Content /&gt啊,有木有</div>
}

<div>
这里就是渲染Body啦.~~不需要写神马&lt;asp:Content /&gt;,其实因为RenderBody()不在有歧义.
</div>

最后显示的页面效果:


问:为什么为什么要推荐方式1呢?

答:因为RenderSection()方法有2个重载.

如果使用第一个只接受一个string类型参数的重载的话.~如果你在具体的View中没有利用@section来定义实现的话,运行会报错.所以需要配合另外一个方法IsSectionDefined()来使用,才能防止报错.

而使用第2个重载就可以利用第二个bool类型的参数指明该Section是否为必须的.所以可以在使用该RenderSection方法的时候直接利用第二个重载,再把bool参数值设为false,即使你在具体的View中没有声明实现@section,运行起来也一如既往地蛋定,不Show黄页.

IV:关于前篇文章中有热心的观众朋友们问到如何在Layout(MasterPage)中读取数据库并初始化页面的问题的解答

在这里只是做个一简单的示范,新建一个类文件,替换如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;
using System.Data.SqlClient; //在这里就用ADO.NET方式吧.EF我接触不久!

namespace Mvc3Application1
{
public class ReaderSQL_Date
{
private static readonly string _SQL_CONN_STR = "server=.\\mssqlserver,1433;uid=sa;pwd=yourpwd;database=student;";

public static IList<StudentEntity> GetAllStudent()
{
//这里仅仅是做演示,生产环境并不这样写
using (SqlConnection conn = new SqlConnection(_SQL_CONN_STR))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "SELECT [Sno],[Sname],[Sage] FROM [dbo].[STUDENT]";

IList<StudentEntity> result = new List<StudentEntity>();
conn.Open();
using (SqlDataReader sdr = cmd.ExecuteReader())
{
while (sdr.Read())
{
result.Add(new StudentEntity
{
S_No = sdr.GetInt32(0),
S_Name = sdr.GetString(1),
S_Age = sdr.GetInt32(2)
});
}
}
//SqlConnection.ClearPool(conn); //可选清理连接池.

return result;
}
}
}

public class StudentEntity
{
public int S_No { get; set; }
public string S_Name { get; set; }
public int S_Age { get; set; }
}
}

_MyLayout.cshtml替换如下:

@{
IList<Mvc3Application1.StudentEntity> studentEntities = Mvc3Application1.ReaderSQL_Date.GetAllStudent();
}
<!DOCTYPE html>

<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<div>

@{
<table>
<tr>
<th>学号</th>
<th>姓名</th>
<th>年龄</th>
</tr>
@foreach (Mvc3Application1.StudentEntity item in studentEntities)
{
<tr>
<td>@item.S_No</td>
<td>@item.S_Name</td>
<td>@item.S_Age</td>
</tr>
}
</table>
}

开始渲染Body<br />
@RenderBody()
渲染Body结束<br />
<br />
开始渲染其他页<br />
@RenderPage("~/Views/Home/ViewPage1.cshtml")
渲染其他页结束<br />
<br />
HOHO,开始学习Section了<br />
开始渲染Section<br />
声明方式1(推荐):SectionA:<br />
@RenderSection("SectionA", false)
-------<br />

声明方式2:SectionB:<br />
@{
if (IsSectionDefined("SectionB"))
{
@RenderSection("SectionB")
}
}
-------<br />
渲染Sction结束<br />
</div>
</body>
</html>

最终显示:

本文到此结束!
在此谢谢各位关注本系列教程和关注博主的朋友们!有大家的[推荐]我会有动力将这个系列一直写下去!

ASP.NET MVC3 系列教程 – 新的Layout布局系统,布布扣,bubuko.com

时间: 2024-11-29 01:10:54

ASP.NET MVC3 系列教程 – 新的Layout布局系统的相关文章

ASP.NET MVC3 系列教程 - 模型

I:基础绑定的实现 1.在前面的两篇基础文章(路由 及 控制器&视图)当中,还没对QueryString的绑定进行介绍,因为我觉得它更适合放在这一章节中去介绍.我们在用WebForm去开发的时候,有时候会利用到QueryString去做一些功能如:http://localhost/First/QueryString.aspx?Sort=Desc,在MVC中,它的实现有两种方式: 控制器代码 public class QueryStringController : Controller { pub

ASP.NET MVC3 系列教程 - Razor视图引擎基础语法

http://www.cnblogs.com/highend/archive/2011/04/09/aspnet_mvc3_razor_engine.html 4. 关于所有带"_"开头的文档 ASP.NET MVC3默认情况下会拒绝所有访问地址以"_"开头的_*.cshtml文档.关于_*.cshtml文档,其实他是WebPages中的一部分,稍后将会详细介绍该以"_"文档的使用说明. 例如访问 http://localhost:7985/_V

ASP.NET MVC3 系列教程 - 部署你的WEB应用到IIS 6.0

I:ASP.NET MVC3 部署的前期工作 1.确认部署的服务器操作系统环境 首先我们确认服务器的操作系统版本 可以从系统命令行工具里输入: systeminfo 获取相关操作系统信息例如 然后再确认IIS版本信息 -> 打开IIS管理工具即可 接着确认.NET Framework的版本 可以在系统命令行工具执行: cd /d %windir%\Microsoft.NET\Framework dir /O 2.选择部署方案 部署方案目前就个人而言,将归纳为 3 种方案 A:带源代码文件的部署方

ASP.NET MVC3 系列教程 – Web Pages 1.0

http://www.cnblogs.com/highend/archive/2011/04/14/aspnet_mvc3_web_pages.html I:Web Pages 1.0中以“_”开头的特别文件(文件命名时不区分大小写) 综上所述得知MVC3的APP初始化顺序为:   (不排除本人未能发现的其他文件类型,但目前据我所知道应用最广的就这三个) 在Web Pages 1.0下,除非你显式以”_”开头命名View.否则你在请求”_”开头的页面时会遇到以下无法服务的页面提示 (这图在Raz

【ASP.NET Identity系列教程(二)】运用ASP.NET Identity

注:本文是[ASP.NET Identity系列教程]的第二篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序的用户管理,以及实现应用程序的认证与授权等相关技术,译者希望本系列教程能成为掌握ASP.NET Identity技术的一份完整而有价值的资料.读者若是能够按照文章的描述,一边阅读.一边实践.一边理解,定能有意想不到的巨大收获!希望本系列博文能够得到广大园友的高度推荐. 14 Applying ASP

【ASP.NET Identity系列教程(三)】Identity高级技术

注:本文是[ASP.NET Identity系列教程]的第三篇.本系列教程详细.完整.深入地介绍了微软的ASP.NET Identity技术,描述了如何运用ASP.NET Identity实现应用程序的用户管理,以及实现应用程序的认证与授权等相关技术,译者希望本系列教程能成为掌握ASP.NET Identity技术的一份完整而有价值的资料.读者若是能够按照文章的描述,一边阅读.一边实践.一边理解,定能有意想不到的巨大收获!希望本系列博文能够得到广大园友的高度推荐. 15 Advanced ASP

ASP.NET 5系列教程 (六): 在 MVC6 中创建 Web API

ASP.NET 5.0 的主要目标之一是统一MVC 和 Web API 框架应用. 接下来几篇文章中您会了解以下内容: ASP.NET MVC 6 中创建简单的web API. 如何从空的项目模板中启动,及添加控件到应用中. 如何配置 ASP.NET 5.0 管道. 在 IIS 外对立部署应用. 本文的目的是从空的项目开始,逐步讲解如何创建应用.当然,您也可以从“Starter Web” 模板开始,它默认包含了MVC 6.权限.记录等其他模块,同时也内置了有效的控制器和视图在其中. 创建空的 A

ASP.NET 5系列教程(七)完结篇-解读代码

在本文中,我们将一起查看TodoController 类代码. [Route] 属性定义了Controller的URL 模板: [Route("api/[controller]")] 所有符合该模板类型的HTTP 请求都会被路由到该controller.在本例中, 路由的命名规范为对应Controller 的前缀,对于TodoController 类,路由模板为 “api/todo”. HTTP 方法 [HttpGet].[HttpPost]和[HttpDelete] 属性定义为 co

ASP.NET 5系列教程 (四):向视图中添加服务和发布应用到公有云

向视图中添加服务 现在,ASP.NET MVC 6 支持注入类到视图中,和VC类不同的是,对类是公开的.非嵌套或非抽象并没有限制.在这个例子中,我们创建了一个简单的类,用于统计代办事件.已完成事件和平均优先级的服务. 1. 添加命名为Services 的文件夹,在该文件夹下添加名称为 StatisticsService.cs 的类: StatisticsService 类代码设计如下: using System.Linq; using System.Threading.Tasks; using