ASP.NET MVC5 学习系列之视图
一、视图约定
当创建一个项目模版时,可以注意到,项目以一种非常具体的方式包含了一个结构化的Views目录。在每一个控制器的View文件夹中,每一个操作方法都有一个同名的视图文件与其对应。(约定大于配置)这就提供了视图与操作方法关联的基础。
public ActionResult Index()
{
return View();
}
视图选择逻辑在/Views/ControllerName目录(这里就是去掉Controller后缀的控制器名)下查找与操作方法同名的视图。此处选择的是/Views/Home/Index.cshtml。与ASP.NET MVC中的大部分方法一样,这一约定是可以重写的。想让Index操作方法渲染一个不同的视图,可以向其提供一个不同的视图名称,代码如下:
public ActionResult Index()
{
return View("NotIndex");
}
对于上面的编码,操作方法依然在/Views/Home目录中查找视图,但选择的不再是Index.cshtml,而是NotIndex.cshtml。如果需要制定完全位于不同目录结构中的视图,编码如下:
public ActionResult Index()
{
return View("~/Views/Example/Index.cshtml");
}
二、 强类型视图
假设需要编写一个显示Album实例列表的视图,一种方法是将专辑添加到ViewBag中,然后在视图中进行迭代。
public ActionResult List()
{
var albums = new List<Album>();
for (int i = ; i < ; i++)
{
albums.Add(new Album { Title = "Product" + i });
}
ViewBag.Albums = albums;
return View();
}
然后,再在视图中迭代显示,如下代码:
<ul>
@foreach (Album a in (ViewBag.Albums as IEnumerable<Album>))
{
<li>@a.Tilte</li>
}
</ul>
注意在枚举之前需要将动态的ViewBag.Albums转换为IEnumerable<Album>类型。为了使代码整洁,可以使用dynamic关键字,但是当访问每个Album对象的属性时,就不能再使用智能感知功能。
<ul>
@foreach (dynamic p in ViewBag.Albums)
{
<li>@p.Tilte</li>
}
</ul>
强类型视图既能获得dynamic的简洁语法,又能获得强类型和编译时检查的好处(比如正确的输入属性和方法名称)。强类型视图允许设置视图的模型类型。因此可以从控制器向视图传递一个在两端都是强类型的模型对象,从而获得智能感知、编译器检查等好处。在Controller方法中,可以通过向重载的View方法中传递模型实例来指定模型,代码如下:
public ActionResult List()
{
var Musics = new List<MusicModels>();
for (int i = ; i < ; i++)
{
Musics.Add(new MusicModels { MusicName = "MusicName" + i.ToString() });
}
return View(Musics);
}
下一步是告知视图哪种类型的模型正在使用@model声明。但要注意这里需要输入模型类型的完全限定类型名(名称空间和类型名称),如下所示
@model IEnumerable<MvcMusicStore.Models.MusicModels>
<ul>
@foreach(MvcMusicStore.Models.MusicModels music in Model)
<li>@music.SingerName</li>
</ul>
如果不想输入模型类型的完全限定类型名,可使用@using关键字,如下所示
@using MvcMusicStore.Models
@model IEnumerable<MusicModels>
<ul>
@foreach(MusicModels music in Model)
<li>@music.SingerName</li>
</ul>
对于在视图中经常使用的名称空间,好的方法是在Views目录下的web.config文件中声明:
<add namespace="MvcMusicStore.Models">
三、 理解ViewBag、ViewData和ViewDataDictionary
之前介绍了使用ViewBag从控制器向视图传递信息,然后介绍了传递强类型模型。现实中,这些都是通过ViewDataDictionary传递的。从技术的角度看,数据从控制器传送到视图是通过一个名为ViewData的ViewDataDictionary(这是一个特殊的字典类)。我们可以使用标准的字典语法设置或读取其中的值:
ViewData["CurrentTime"] = DateTime.Now;
尽管这种语法现在也能用,但是MVC3提供了更简单的语法,可以利用C#4的dynamic关键字。ViewBag是ViewData的动态封装器。这样我们就可以按照下面的方式来设置值:
ViewBag.CurrentTime = DateTime.Now;
ViewBag.CurrentTime和ViewData["CurrentTime"] 起到了等同的作用。一般来说,大部分代码使用ViewBag,而不是ViewData,这两种语法并不存在技术上的差异,仅仅是因为ViewBag相对于字典语法而言看上去好看。
注意,ViewBag和ViewData的差异:
- 只有当要访问的关键字是一个有效的C#标识符时,ViewBag才起作用。例如,如果在ViewData["Key With Spaces"]中存放一个值,那么就不用使用ViewBag访问,因为无法通过编译。
- 动态值不能作为一个参数传递给扩展方法,因为C#编译器为了选择正确的扩展方法,在编译时必须知道每一个参数的真正类型。
四、Razor语法
在演示Razor语法的使用之前,我们需要做一些准备工作。
1.打开VS创建一个ASP.NET MVC空项目,很简单,就不具体演示了。
2.添加一个Model。在项目的Models文件夹中添加一个名为Product的类。代码如下:
namespace MvcApplication1.Models {
public class Product {
public int ProductID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { set; get; }
}
}
3.添加一个Controller。右击项目中的Controllers文件夹,选择添加控制器,命名如下图所示:
点添加后,对ProdcutController中的代码进行如下编辑:
using System.Web.Mvc;
using MvcApplication1.Models; namespace MvcApplication1.Controllers
{
public class ProductController : Controller
{
public ActionResult Index()
{
Product myProduct = new Product {
ProductID = ,
Name = "苹果",
Description = "又大又红的苹果",
Category = "水果",
Price = 5.9M
};
return View(myProduct);
}
}
}
4.添加一个View。右击Index方法,选择添加视图,在弹出的窗口进行如下配置:
点添加后,系统自动帮我们创建一个Product文件夹和一个Index.cshtml文件,Index.cshtml内容如下:
@model MvcApplication1.Models.Product @{
ViewBag.Title = "Index";
} <h2>Index</h2>
5.修改默认路由。为了方便,我们应该让应用程序启动时直接导向我们需要的请求处理(此处是Product/Index)。打开Global.asax文件,找到注册路由RegisterRoutes方法下的routes.MapRoute方法,把controller的值改为“Product”,如下所示:
routes.MapRoute(
"Default", // 路由名称
"{controller}/{action}/{id}", // 带有参数的 URL
new { controller = "Product", action = "Index", id = UrlParameter.Optional } // 参数默认值
);
使用Model对象介绍Razor语法,让我们从Index.cshtml文件的第一行开始:
@model MvcApplication1.Models.Product
Razor语句都是以@符号开始的。每个视图都有自己的Model属性(通过@Model调用)。上面这句代码的意思是将本视图的Model属性的类型指向MvcApplication1.Models.Product类型,这就实现了强类型。强类型的好处之一是类型安全,如果写错了Model对象的某个成员名,编译器会报错;另一个好处是在VS中可以使用VS中的代码智能提示自动完成类型成员调用的代码编写。 当然这句代码不要程序也可以正常运行,只是给编写代码造成了一定的困难。
视图中的Model属性用于存放控制器(Controller)传递过来的model实例对象(本示例中ProductController通过“return View(myProduct)”传递给Index视图),下面的代码演示了如何调用该model对象:
@model MvcApplication1.Models.Product @{
ViewBag.Title = "Index";
}
<!-- 调用Product实例的Name属性 -->
<h2>名称:@Model.Name</h2>
注意,第一行代码用于声名Model属性类型用的是@model <Model类型名>(小写m),而调用控制器传递过来的Model对象用的是@Model.<属性名>(大写M)。按F5运行效果如下:
(一)使用表达式
上面讲的使用Model对象是很常用的一种Razor代码。其实上面示例中的@Model.Name就是一个简单的表达式,表示向Web页面呈现Model.Name的文本值。Razor语法中的表达式除了可以使用Model对象,也可以使用几乎任何一个其他可访问权限范围内的对象,来向Web面面输出该对象成员的文本值。如下代码所示:
@model MvcApplication1.Models.Product @{
ViewBag.Title = "Index";
} 现在的时间是: @DateTime.Now.ToShortTimeString()
运行效果如下:
这种使用对象的简单表达式(@DateTime.Now.ToShortTimeString()和@Model.Name),在这我们不防称之为对象表达式。除了对象表达式,还可以是其他任意的有返回值的表达式,如条件表达式。如下面代码所示:
@model MvcApplication1.Models.Product @{
ViewBag.Title = "Index";
} 现在的时间是: @DateTime.Now.ToShortTimeString() <br/>@(DateTime.Now.Hour>22 ? "还早,再写一会吧!" : "该睡觉咯!")
运行效果如下:
注意,一般使用非对象表达式时都需要用小括号括起来。
(二)使用代码块
和表达式的使用方式一样,Razor语法中也可以使用由{}括起来的单个C#过程控制代码块(如if、switch、for等)。使用方式如下:
@model MvcApplication1.Models.Product @{
ViewBag.Title = "Index";
} @if (Model.Price > 5M) {
string test = "买不起!";
<p>@Model.Name <b>太贵了!</b> @test </p>
}
效果如下:
由{}括起来的代码块内可以写任何C#代码,也可以使用任何HTML标签。但需注意的是,当控制语句内只有一句代码时不能像写C#后台代码一样省略大括号。还有一种更常用的使用代码块的方式。你也可以通过以@{开始,以}闭合的方式来使用代码块,它可以把多个代码块放在一起,开成一个更大的代码块。如下代码所示:
@model MvcApplication1.Models.Product @{
ViewBag.Title = "Index";
}
@{
if(Model.Category=="水果"){
string test="是一种水果。";
@Model.Name @test
}
if (Model.Price > 5M) {
string test = "买不起!";
<p>@Model.Name <b>太贵了!</b> @test </p>
}
}
运行结果如下:
(三)使用@:和text标签
我们注意到,在代码块中,要么是C#代码,要么是HTML标签,不能直接写纯文字,纯文字须包裹在HTML标签内。但如果需要在代码块中直接输出纯文字而不带HTML标签,则可以使用@:标签,在代码块中输出纯文本文字非常有用。如下代码所示:
@if (Model.Price > 5M) {
@Model.Name@:太贵了 。
<br />
@: @@:后面可以是一行除@字符以外的任意文本,包括<、>和空格,怎么写的就怎么输出。
<br />
@: 如果要输出@符号,当@符号前后都有非敏感字符(如<、{、和空格等)时,可以直接使用@符号,否则需要使用两个@符号。
}
注意@符号的使用。上面代码运行效果如下:
使用@:标签在代码块中输出一行不带html标签的文本非常方便,但如果需要在代码块中输出续或不连续的多行纯文本,则使用text标签较为方便,如下代码所示:
@if (Model.Price > 5M) {
<text>
名称:<b>@Model.Name</b><br />
分类:<b>@Model.Description</b><br />
价钱:<b>@Model.Price</b><br />
<pre>
测试行一: <a>aaaa</a>
测试行二: @@ fda@aaa
</pre>
</text>
}
运行结果:
五、简单分部视图
创建一个PartialView,在解决方案资源管理器中右键点击Shared文件夹选择添加->MVC 5 分部页(Razor)。如下图所示:
文件命名为PartialPage.cshtml,写入如下代码:
<h2>This is a partial page.</h2>
这样我们就创建好了一个简单的分部视图,现在我们来创建一个Controller和View来调用它。
在Controllers文件夹下创建PartialViewController.cs并写入如下代码:
一个最简单的Controller,就是为了让大家好理解。右键点击上面的"Index"函数名,选择添加视图。系统会在~\Views\PartialView\文件夹下创建Index.cshtml文件,在这个文件中写入如下代码:
上面代码中第1-3行表示在分部视图中不用加载模板。<hr />是下图所示的分隔线。
从下面显示结果可以看出,PatialPage.cshtml中的内容被显示了两次,这对应两个不同的调用分部视图的函数。第6行Html.Partial函数的作用是返回所调用的PartialView中的内容。其所在的View会负责输出其返回的内容。而第9行的代码则是直接输出所调用的PartialView中的内容。
如果还是不清楚Partial和RenderPartial的关系,可以这样类比:比如我们有一个string叫s,Partial和RenderPartial的关系就相当于s.ToString()和Response.Write(s.ToString())的关系一样。前者是返回内容,后者是输出内容。
(一)带Model的分部视图
前面只是创建了一个静态分部视图,下面我们来把它改造一下来显示Model数据。修改~\Views\PartialView\Index.cshtml文件,代码如下:
上面的第6和9行,加入了第二个参数,是一个数字。这个数字就是我们要传给PartialView的Model。修改~\Views\Shared\PartialView.cshtml文件,内容如下:
@model int
<h2>This is a partial page @Model.</h2>
第1行表示传入的model是int类型。第2行把这个数字显示出来。显示结果如下:
(二)使用ChildAction调用分部视图
前面调用PartialView的方式都是通过一个View来调用PartialView。下面我们来介绍通过View调用ChildAction来返回PartialView。
首先在PartialViewController.cs里面写一个ChildAction代码如下:
第1行,在ChildAction函数的前面写上[ChildActionOnly]表示这个Action只能作为ChildAction使用。ChildAction返回partialView的好处就是在Action里可以做一些处理和控制。这里第4到16行就是根据获得的时间返回不同的问候语。第17行返回其对应的PartialView并传入greetings作为Model。右键点击ChildAction函数名选择创建视图,取名为ChildAction。写入如下代码:
@model string
<h2>@Model</h2>
这个PartialView很简单,就是把传入的Model显示出来。修改~\Views\PartialView\Index.cshtml文件,代码如下:
(三)ajax无刷新更新分部视图
要通过ajax来调用ChildAction返回PartialView,首先要去掉ChildAction开头写的[ChildActionOnly]。因为这种调用方法不算ChildAction调用。然后修改~\Views\PartialView\Index.cshtml文件,代码如下:
这样就完成了无刷新更新局部页面数据。在视图里有多种方法可以 加载部分视图,包括:Partial() Action() RenderPartial() RenderAction() RenderPage() 方法。以下是这些方法的差别:
(四)Partial 与 RenderPartial 方法
1. Razor 语法:@Html.Partial() 与 @{Html.RenderPartial();}
2. 区别:Partial 可以直接输出内容,它内部是 将 html 内容转换为
string 字符(MVCHtmlString),然后缓存起来, 最后在一次性输出到页面。显然,这个转换的过程,会降低效率,所以通常使用 RenderPartial 代替。
(五)RenderPartial 与 RenderAction 方法
1. Razor 语法:@{Html.RenderPartial();} 与 @{Html.RenderAction();}
2. 区别:RenderPartial 不需要创建 Controller 的 Action ,而 RenderAction 需要在 Controller 创建要加载的 Action。
RenderAction 会先去调用 Contorller 的 Action ,最后再 呈现视图,所以这里 页面会在 发起一个链接。
如果这个部分视图只是一些简单 的 html 代码,请使用 RenderPartial。 但如果这个部分视图 除了有 html 代码外,还需要通过读取数据库里的数据
来渲染,就必须使用 RenderAction 了,因为它可以在 Action 里调用 Model里的方法读取数据库,渲染视图后在呈现,而 RenderPartial 没有 Action,所以无法做到。
(六)RenderAction 与 Action
1. Razor 语法:@{Html.RenderAction();} 与 @Html.Action();
2. 区别:Action 也是直接输出,和 Partial 一样,也存在一个转换的过程。不如 RenderAction 直接输出到当前HttpContext 的效率高。
(七)RenderPage 与 RenderPartial 方法
1. Razor 语法:@{Html.RenderPartial();} 与 @RenderPage()
2. 区别:也可以使用 RenderPage 来呈现部分,但它不能使用 原来视图的 Model 和 ViewData ,只能通过参数来传递。而 RenderPartial 可以使用原来视图的 Model 和 ViewData。
ASP.NET MVC5 学习系列之视图的更多相关文章
- MVC5学习系列--Razor视图(一)
前言 嗷~小弟我又出现了~咳咳..嚎过头了, 先说一说为什么写这个吧,~首先肯定是我自己需要学(废话 - -,)//,之前也写过MVC4的项目,嗯..但是仅限于使用并没有很深入的每个模块去了解, 这段 ...
- ASP.NET MVC5 学习系列之初探MVC
一.由问题看本质 (一)什么是MVC? MVC是Model-View-Controller的简称.它是在1970年引入的软件设计模式.MVC 模式强迫关注分离 — 域模型和控制器逻辑与UI是松耦合关系 ...
- ASP.NET MVC5 学习系列之模型绑定
一.理解 Model Binding Model Binding(模型绑定) 是 HTTP 请求和 Action 方法之间的桥梁,它根据 Action 方法中的 Model 类型创建 .NET 对象, ...
- ASP.NET MVC5 学习系列之表单和HTML辅助方法
一.表单 (一)Action和Method特性 Action特性用以告知浏览器信息发往何处,因此,Action特性后面需要包含一个Url地址.这里的Url地址可以是相对的,也可以是绝对的.如下Form ...
- ASP.NET MVC5学习系列——身份验证、授权
一.什么是身份验证和授权 人们有时对用户身份验证和用户授权之间的区别感到疑惑.用户身份验证是指通过某种形式的登录机制(包括用户名/密码.OpenID.OAuth等说明身份的项)来核实用户的身份.授权验 ...
- ASP.NET MVC学习系列(二)-WebAPI请求
继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现 ...
- ASP.NET MVC学习系列(二)-WebAPI请求(转)
转自:http://www.cnblogs.com/babycool/p/3922738.html 继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的g ...
- [转]ASP.NET MVC学习系列(二)-WebAPI请求 传参
[转]ASP.NET MVC学习系列(二)-WebAPI请求 传参 本文转自:http://www.cnblogs.com/babycool/p/3922738.html ASP.NET MVC学习系 ...
- ASP.NET MVC学习系列(二)-WebAPI请求 转载https://www.cnblogs.com/babycool/p/3922738.html
继续接着上文 ASP.NET MVC学习系列(一)-WebAPI初探 来看看对于一般前台页面发起的get和post请求,我们在Web API中要如何来处理. 这里我使用Jquery 来发起异步请求实现 ...
随机推荐
- php的mysqli_connect函数显示 No such file or directory错误以及localhost换成127.0.0.1执行成功
Centos7环境-php7-MariaDB5.5.60 (新安装的php7,执行php -m 显示有mysqli模块,php.ini没有改其它) 测试代码为: <?php //~ echo d ...
- Java与数据库学习总结
1.连接数据库 package utils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Re ...
- 初次使用vue-cli3 来搭建项目
1,细数项目中使用的技术:vue, vue-router, vuex ,axios,vue-cli3, 快速建站. 2,mock技术使用的express-mockjs . 由于cli3 最新版的话缺少 ...
- Msql浅析-基础命令(二)
篇幅简介 一.Msql数据类型 1.整型 tinyint, 占 1字节 ,有符号: -128~127,无符号位 :0~255 smallint, 占 2字节 ,有符号: -32768~32767无符 ...
- Zookeeper -- 命令
zkServer.sh start //启动zk进程 zkServer.sh stop //关闭zk进程 zkServer.sh status //查看zk状态 zkCli.sh //启动本地zk客户 ...
- FreeRTOS内存管理
简介 Freertos的内存管理分别在heap_1.c,heap_2.c,heap_3.c,heap_4.c,heap_5.c个文件中,选择合适的一种应用于嵌入式项目中即可. 本文的图片中 红色部分B ...
- CentOS 7.2搭建xl2tp服务器
## 1.下载xl2tpd.tar.gz源码包 ```wget http://pkgs.fedoraproject.org/repo/pkgs/xl2tpd/xl2tpd-1.3.8.tar.gz/d ...
- Centos7 安装 Python 的笔记
Centos7 安装 Python 的笔记 注意:系统自带的Python2.7不要改动,最好也不要出错,不然yum之类的工具可能会出错. 安装Python3.7.0 TensorFlow对Python ...
- 搜索引擎的选择与在chrome上的设置
1 优缺点分析 百度:广告多,但是电脑端可以用Adblock Plus屏蔽:搜索内容有很多百度自家内容,如百家号.百度知道.百度文库.百度贴吧等,在搜索教程的时候很实用,但是不适合偏专业性搜索,很多 ...
- 20155220java实验二 面向对象程序设计 实验报告
一.实验内容 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握UML建模 熟悉S.O.L.I.D原则 了解设计模式 实验步骤 (一)单元测试 (1) 三种代码 伪代码 产 ...