详解ASP.NET MVC 3新的Layout布局系统

作者:控件中国网   出处:互联网   2015-07-17 22:52:22   阅读:6

今天们谈到的是ASP.NET MVC 3中有关新的Layout布局系统,在MVC3当中们可以利用新的Layout布局系统来代替掉原来在MVC2当中使用的MasterPage。


 

AD: Dynamic .NET TWAIN是一款用于.NET桌面应程序下的扫描控件,可以从任何兼容TWAIN的驱动获取图像,市面上少有的分发完全免费的扫描控件,控件中国网:023-6787 0900

 

大家先看下面的代码:


 

 !------------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以来从没有间断过的合作关系,可谓缘分呀!).


 

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


 

image


 

下面进行逐一介绍:


 

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属性.


 

B.@RenderBody()方法:直接渲染整个View到占位符处,而不需要原来所使用的 asp:Content / .


 

C.@RenderPage()方法:渲染指定的页面到占位符处.


 

D.@RenderSection方法:声明一个占位符,和原来的 asp:ContentPlaceHolder / 功能类似.


 

E.@section标记:对@RenderSection方法声明的占位符进行实现,和原来的 asp:Content / 功能类似.


 

1.1.@RenderBody()方法的使用


 

首先在~/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啦.~~不需要写神马 asp:Content / ,其实因为RenderBody()不在有歧义.   /div  


 

最后输出截图为:

image


 

这个与之前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):


 

image


 

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


 

1.2.@RenderPage()方法的使用


 

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


 

 div  这里是~/Views/Home/ViewPage1.cshtml,老规矩:还是不用写 asp:Content /   /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  


 

们来看最终的输出效果:


 

image


 

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


 

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


 

image


 

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


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

好,写到这里开始介绍上一章节中没有介绍完的两个东西:@RenderSection方法和@section标记


 

1.@RenderSection()方法等价于 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:也不需要写神马 asp:Content / gt啊,有木有 /div  }   div  这里就是渲染Body啦.~~不需要写神马 asp:Content / ,其实因为RenderBody()不在有歧义.   /div  


 

最后显示的页面效果:


 

image


 



image

问:为什么为什么要推荐方式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  


 

最终显示:

Dynamic .NET TWAIN是一款用于.NET桌面应程序下的扫描控件,可以从任何兼容TWAIN的驱动获取图像,市面上少有的分发完全免费的扫描控件,控件中国网:023-6787 0900
 

Copyright© 2006-2015 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 渝ICP备12000264号 法律顾问:元炳律师事务所
客服软件
live chat