APS.NET MVC + EF (04)---路由和数据传递
4.1 视图引擎
ASP.NET MVC 提供两种视图引擎:ASPX(C#)和Razor(CSHTML),推荐使用Razor。
4.1.1 Razor的语法
在Razor视图中,所有的服务器端代码都是围绕@展开的,下面介绍@使用的各种语法形式和应用情况。
- @( expression) 或 @ expression
@是Razor中的一个重要符号,它被定义为Razor服务器代码块的开始符号。例如,我们可以在View中直接写C#代码输出日期
<p> @Datetime.Now.ToStirng()</p> |
@(expression)一般可以吧"()"省略,但这只限于@后紧邻变量或对象的情况,如果后面是常数,则必须加"()",如下面的用法。
@("razor视图".ToString() )
如果去掉()则不能正常解析。
- 语句块
在Razor视图引擎中,我们可以使用@{code}来定义一段代码块。并支持与HTML代码混写。如下面代码所示。
@{ var stu = new RazorDemo.Models.Student(); stu.StudentName = "王五"; stu.Gender = "男"; <p>姓名:@stu.StudentName</p> <p>性别:@stu.Gender</p> } @foreach (var stu in students) { <p>姓名:@stu.StudentName</p> <p>性别:@stu.Gender</p> } @if (stu.Gender == "男") { <p>姓名:@stu.StudentName</p> <p>性别:@stu.Gender</p> } |
- 输出特殊字符
如果要输出"@"符号,可以使用"@@"进行转义,如:
<p>@@2013 copy right</p> |
- 引用命名空间
@using RazorDemo.Models |
- 注释
@* 被注释的内容 *@ |
4.1.2 布局页
Razor的布局有助于使应用程序中的多个视图保持一致外观。如果熟悉WebForm的话,其中母版页和布局的作用基本上是相同的,但是布局提供了更加简洁的语法和更强大的灵活性。
可以使用布局为网站定义公共模板(或只是其中的一部分)。公共模板包含一个或多个占位符,应用程序中的其他视图为他们提供内容。从某些角度来看,布局很像视图的抽象基类。
下面来看一个简单的布局。这里称这个布局文件为SiteLayout.cshtml
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> </head> <body> <div id="main-content"> @RenderBody() <!--占位符--> </div> </body> </html> |
它看起来很像一个标准的Razor视图,但需要注意的是在视图中由一个@RenderBody调用。这是一个占位符,用来标记使用这个布局的视图将渲染他们的主要内容的位置。多个Razor视图现在可以利用这个布局来显示一致的外观。
接下来看一个使用这个布局的例子Index.cshtml 。
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/SiteLayout.cshtml"; } <h2>这是主页内容</h2> |
上面这个视图通过Layout属性来指定布局页面。当渲染这个视图时,它的HTML内容将被放在SiteLayout.cshtml中的id属性为main-content的div元素中,最后生成的html页面如下。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> </head> <body> <div id="main-content"> <h2>这是主页内容</h2> </div> </body> </html> |
注意视图内容,其中标题和内容都是视图提供的,除此以外都是布局提供的。
在一个布局页中只允许有一个@RenderBody()占位符,如果需要多个占位符,可以使用@RenderSection( ) 方法来完成,例如再SiteLayout.cshtml页面上添加一个页脚占位符。
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>@ViewBag.Title</title> </head> <body> <div id="main-content"> @RenderBody() </div> <footer> @RenderSection("Footer") </footer> </body> </html> |
在不做任何改变的情况下再次运行前面的视图,将会抛出一个异常,提示没有定义Footer。默认情况下,视图必须为布局中定义的每一个占位符section提供相应的内容。
更新后的Index.cshtml 。
@{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/SiteLayout.cshtml"; } <h2>这是主页内容</h2> @section Footer { this is the <strong>这是底部</strong> } |
@RenderSection( )方法有一个重载,第二个参数是bool类型,指明该Section是否为必须的。所以可以在使用该RenderSection方法的时候直接利用第二个重载,再把bool参数值设为false,即使你在具体的View中没有声明实现@section,运行起来也不会报错了。
在项目中,如果每个页面都使用布局页,那么就必须在每个内容页中都要使用 Layout 进行声明,这就形成了代码冗余。
_ViewStart.cshtml页面可以用来消除这种冗余。这个文件中的代码先于同目录下任何视图代码的执行。这个文件也可以递归地应用到子目录下的任何视图。
当创建一个默认的ASP.NET MVC项目时,你将会注意到Views目录下会自动添加一个_ViewStart.cshtml文件,它指定了一个默认布局。
@{ Layout = "~/Views/Shared/_Layout.cshtml"; } |
这样在内容页中就不用再指定 Layout 了。
4.2 路由
4.2.1 为什么需要路由
在前面的内容中,我们已经初步接触了路由的定义代码,示例1所示代码能将"/Home/Index/0"、/Home/Index"、/Home"、"/"多种形式的URL指向同一个页面。
示例1
routes.MapRoute( "Default", // 路由名称 "{controller}/{action}/{id}", // 带有参数的URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } // 参数默认值 ); |
在系统中使用路由的好处有两点。
- 屏蔽物理路径,提高安全性
- 有利于搜索引擎的优化
4.2.2 路由规则
示例1中,MapRoute()中URL的参数值是"{controller}/{action}/{id}",称之为URL模式。该模式是一种字符串,包括一些固定的字符字面量和占位符,占位符由一对{}表示,其语法为:
字面量{占位符}字面量{占位符}字面量…{占位符}字面量
在上述语法中字面量可能是一个固定的字符,比较常见的是"/",也可能是一个字符串,如"Users"。占位符也是一个字符或字符串。
表4-1 URL模式匹配示例
序号 |
URL模式 |
匹配的URL示例 |
1 |
{controller}/{action}/{id} |
/books/Edit/1,/Books/Detail/2 |
2 |
{first}/{second}/{third} |
/books/Edit/1,/Books/Detail/2 |
3 |
{table}/Detail.aspx |
/Users/Detail.aspx, /Books/Detail.aspx |
4 |
Blog/{action}/{id} |
/Blog/Show/1001, /Blog/delete/1001 |
5 |
{language}-{country}/{action} |
/zh-cn/display, /en-us/list |
注意事项:
- URL模式匹配不区分大小写。
- 两个占位符之间不能连续。
- "/"和一般的字面量相比,是比较特殊的。
- 不能以"/"或"~"字符开头,不能包含"?"。
除了上面一些规则为,还有一些特殊的模式。
(1) * 匹配
* 用来匹配剩余部分。如URL模式"{controller}/{action}/{query}/{*plus}"匹配的URL,产生的部分路由数据如表4-2所示。
序号 |
路由模式 |
路由数据 |
1 |
/home/index/select/a/b |
Key=plus, Value= a/b |
2 |
/home/index/select/a/b/c |
Key=plus, Value= a/b/c |
3 |
/home/index/select/ |
Key=plus, Value= |
(2) 贪婪匹配
例如URL模式: {filename}.{ext}
如果匹配"/food.xml.aspx",则会产生路由数据如下:
filename= food.xml, ext=aspx
所谓贪婪匹配就是,在模式匹配过程中,寻找字面量时不是找到第一个后就放弃,而是贪婪的寻找到最有一个为止。
(3) 默认值
路由可以有默认值的,如示例1中指定的默认值。如果没有默认值,只能使用诸如"book/eidt/0"这样的地址去匹配,使用时非常不方便。
在使用路由默认值时要注意以下两点。
- 只提供中间参数的默认值不起作用。
如只提供 action="index", 则"/home/0"不匹配,只能是"/home/index/0"
- 包含字面量时默认值不起作用("/"除外)
如:对于模式{controller}-{action},提供默认值action="index", 则"/home-"不能匹配,只能使用 /home-index
(4) 路由约束
可以给路由参数增加正则表达式约束,如示例2所示。
routes.MapRoute( "Default", // 路由名称 "{year}/{month}/{day}", // 带有参数的URL new { controller = "Home", action = "Index", id = UrlParameter.Optional } , // 参数默认值 constraints: new { year=@"\d{4}", month=@"\d{2}", day=@"\d{2}" } ); |
(5)多个路由
如果有多组路由时,排在最前面的优先匹配。
4.2.3 路由数据
RouteData对象用来保存URL模式和实际URL匹配产生的路由数据,这些路由数据以键-值对的形式保存。如:
表4-2 URL模式匹配示例
序号 |
URL模式 |
匹配的URL示例 |
路由数据 |
1 |
{controller}/{action}/{id} |
/books/Edit/1, /Books/Detail/2 |
Key=Controller,Value=Books Key=action,Value=Edit Key=id,value=1 |
2 |
{first}/{second}/{third} |
/books/Edit/1, /Books/Detail/2 |
Key=first,Value=Books Key=second,Value=Edit Key=third,value=1 |
3 |
{table}/Detail.aspx |
/Users/Detail.aspx, |
Key=table, value=Users |
4 |
Blog/{action}/{id} |
/Blog/Show/1001 |
Key=action, value=show Key=id, value=1001 |
5 |
{language}-{country}/{action} |
/zh-cn/display, |
Key=language, value=zh Key=country,value=cn Key=action, value=display |
可以使用如下代码在动作方法中读取路由中的值:
string id = RouteData.Values[ "id" ] ;
在使用时注意验证是否为null。
4.3 数据传递---从控制器到视图
在ASP.NET MVC中,使用RouteData对象可以方便的获取URL中的参数值。同样,也提供了若干对象可以从控制器向视图传递数据。
4.3.1 ViewData对象
ViewData是一种字典集合数据,同时属于视图基类和控制器基类的属性。常见的用法是在控制器中写入数据,在视图中读取数据。如示例2所示。
示例2
//控制器代码 public class HomeController : Controller { public ActionResult Index() { ViewData["data"] = "Hello,MVC!"; return View(); } } //视图代码 <h1>@ViewData["data"]</h1> |
注意:ViewData 的 Value 是 Object 类型。
4.3.2 ViewBag对象
ViewBag是 dynamic 类型的对象,同时属于视图基类和控制器基类的属性,用法如示例3所示。
示例3
//控制器代码 public class HomeController : Controller { public ActionResult Index() { ViewBag.data = "Hello,MVC!"; return View(); } } //视图代码 <h1>@ViewBag.data</h1> |
本质上,ViewBag是对ViewData数据的包装,也就是说两个对象中的数据是可以相互读取的。
4.3.3 TempData对象
TempData的用法和ViewData用法相似,但和ViewData保存的数据互不干扰。如示例4所示。
示例4
//控制器代码 public class HomeController : Controller { public ActionResult Index() { TempData["data"] = "Hello,MVC!"; return View(); } } //视图代码 <h1>@TempData["data"]</h1> |
在实际开发中,TempData主要用来跨请求传递数据,也就是说跨越动作方法传递数据,如示例5所示。
示例5
//控制器代码 public class HomeController : Controller { public ActionResult Index() { TempData["data"] = "来自Index()的数据"; Response.Redirect("~/Home/Detail"); return View(); } public ActionResult Detail() { return View(); } <!-- Detail.cshtml 视图代码 --> <h1>@TempData["data"]</h1> |
需要注意的是,如果TempData中的数据被使用过(从视图中输出),就会被清除。如果没有被使用过,那么它保存的时间和Session相同。
4.3.4 强类型视图
在使用ViewBag 向视图传递数据时,有一个明显的缺陷就是在使用时要做数据类型转换。有一种更好的方式就是使用强类型视图。在添加视图的时候,在向导对话框中选择"Empty模板",如图4-1所示,并选择模型类。这样创建完成的视图基类就变成了 System.Web.Mvc.ViewPage<T>。
图4-1 创建强类型视图
如果使用强类型视图,则在控制器中传递数据的方式变成直接使用 View()的一个带"model"的参数的重载方法。在视图中可以直接通过模型类的属性使用传递的数据。如示例6所示。
示例6
//动作方法中的代码 Book book = manager.GetBookById(id); return View(book); //视图中的代码 <div> 作者: @Model.Author 著 <br /> 出版社:@Model. Publisher.Name </div> |
4.4 案例:实现带搜索条件和分页的列表展示
略
APS.NET MVC + EF (04)---路由和数据传递的更多相关文章
- APS.NET MVC + EF (05)---控制器
Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的交互,并且负责协调Model与View之间数据传递,是ASP.NET MVC框架核心.Controller为ASP. ...
- APS.NET MVC + EF (14)---项目框架搭建
一:框架搭建 1:先创建Model. 2:创建数据访问接口层.IUserInfoDal 在该接口中定义了常见的方法CURD以及分页方法. public interface IUserInfoD ...
- APS.NET MVC + EF (02)---深入理解ADO.NET Entity Framework
2.7 深入理解Entity Framework 性能问题几乎是一切ORM框架的通病,对于EF来说,引起性能低的原因主要在以下几个方面. 复杂的对象管理机制为了在.NET中更好地管理模型对象,EF提供 ...
- Asp.Net Mvc 控制器与视图的数据传递
数据传递也就是控制器和视图之间的交互,比如在视图中提交的数据,在控制器怎么获取,或者控制器从业务层获得一些数据,怎么传递到视图中,让视图显示在客户端呢?带着这些疑问,我们接着看.. 下面 ...
- mvc中的几个数据传递
1.ViewData对象 ViewBagData是一种字典集合数据同时属于视图基类和控制器基类的属性. 实例: //控制器 public class HomeController:Controller ...
- 【部分】Asp.Net Mvc 控制器与视图的数据传递
原文:https://www.cnblogs.com/lsgsanxiao/p/5105639.html 数据传递也就是控制器和视图之间的交互,比如在视图中提交的数据,在控制器怎么获取,或者控制器从业 ...
- APS.NET MVC + EF (08)---数据注解和验证
对于Web开发人员来说,用户输入验证一直是一个挑战.不仅在客户端浏览器中需要执行验证逻辑,在服务器端也需要执行.如果觉得验证是令人望而生畏的繁杂琐事,ASP.NET MVC框架提供了数据注解的方式帮助 ...
- APS.NET MVC + EF (07)---表单和HTML辅助方法
在ASP.NET MVC中,可以借助HtmlHelper 对象来输出页面内容,提高开发效率.下面,我们将介绍一些常用的辅助方法. 7.1 HTML辅助方法 BeginForm 该辅助方法主要用来产生& ...
- APS.NET MVC + EF (03)---初始MVC
3.1 MVC简介 MVC(Model-View-Controller,模型—视图—控制器模式)用于表示一种软件架构模式.它把软件系统分为三个基本部分:模型(Model),视图(View)和控制器(C ...
随机推荐
- UDP基础
UDP主要特点: (1)UDP是无连接的,发送数据不需要建立连接,减少了开销和发送数据之前的时延. (2)UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持连接状态表. (3)UDP面向报 ...
- LCD硬件原理
想象一下,屏幕的后面有一个电子枪,电子枪位于某个像素的背后,然后向这个像素发射红绿蓝三原色,从而就可以组成任意一种颜色.简单的说,电子枪在像素的背后一边移动,一边向像素发射红绿蓝. 如果要编写出LCD ...
- python爬取全站壁纸代码
#测试网址:https://www.ivsky.com/bizhi/ #需要安装的库:requests,bs4 #本人是个强迫症患者,为了美观添加数个print(),其并没有实际意义,若是不爽删去即可 ...
- NetworkManager需要与不需要
需要: 1.nmcli配置网络 不需要: 1. ifcfg-eth1:0(网卡的子接口配置文件)生效
- 回溯法 | n皇后问题
今早上看了一篇英语阅读之后,莫名有些空虚寂寞冷.拿出算法书,研读回溯法.我觉得n皇后问题完全可以用暴力方式,即先对n个数进行全排列,得到所有结果的下标组合,问题规模为n!. 全排列花了比较久的时间才编 ...
- 【转】Web实现前后端分离,前后端解耦
一.前言 ”前后端分离“已经成为互联网项目开发的业界标杆,通过Tomcat+Ngnix(也可以中间有个Node.js),有效地进行解耦.并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务架构 ...
- 删除list集合中某些数据
去除list集合中不符合条件的数据 List<DictVo> applyStateList = SingletonHoldResource.getInstance().getList(Fr ...
- Xcode一个project多个target
project添加target https://blog.csdn.net/vbirdbest/article/details/53466009 https://www.cnblogs.com/Bob ...
- winform自定义分页控件
1.控件代码: public partial class PagerControl : UserControl { #region 构造函数 public PagerControl() { Initi ...
- Hive常见错误
1.root is not allowed to impersonate root 修改etc/hadoop/core-site.xml,增加如下配置: <property> <na ...