ASP.NET MVC5高级编程 之 视图

时间:2022-09-09 11:11:35

1.1理解视图约定

当创建一个项目模版时,可以注意到,项目以一种非常具体的方式包含了一个结构化的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");
}

 1.2 强类型视图

假设需要编写一个显示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对象的属性时,就不能再使用智能感知功能。

1 <ul>
2 @foreach (dynamic p in ViewBag.Albums)
3 {
4 <li>@p.Tilte</li>
5 }
6 </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">

1.3 理解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#编译器为了选择正确的扩展方法,在编译时必须知道每一个参数的真正类型。

2.视图模型

在操作方法上右击 --> “添加视图”

ASP.NET MVC5高级编程 之 视图

弹出添加视图页:

ASP.NET MVC5高级编程 之 视图

  • View name:当从一个操作方法的上下文中打开这个对话框时,视图的名称默认被填充为操作方法的名称。视图的名称是必须有的。
  • Template:一旦选择一个模型类型,就可以选择一个基架模版。这些模版利用Visual Studio模版系统来生成基于选择模型类型的视图。
  • 引用脚本库:这个选项用来指示要创建的视图是否应该包含指向JavaScript库(如果对视图有意义的话)的引用。默认情况下,_Layout.cshtml文件既不引用jQuery Validation库,也不引用Unobtrusive jQuery Validation库,只引用主jQuery库。

当创建一个包含数据条目表单的视图(如Edit视图或者Create视图)时,选择这个选项会添加对jqueryval捆绑的脚本引用。如果要实现客户端验证,那么这些库就是必须的。除这种情况外,完全可以忽略这个复选框。

  • 创建一个分部视图:选择这个意味着要创建的视图不是一个完整的视图,因此,Layout选项是不可选用的。生成的部分视图除了在其顶部没有<html>标签和<head>标签外,很像一个常规的视图。
  • 使用布局页:这个选项决定了要创建的视图是否引用布局,还是成为一个完全独立的视图。如果选择使用默认的布局,就没必要指定一个布局了,因为在_ViewStart.cshtml文件中已经指定了布局。这个选项是用来重写默认布局文件的。

2.2 Razor视图引擎

ASP.NET MVC中提供了两种不同的视图引擎:较新的Razor视图引擎和较早的WebForms视图引擎。

Razor中的核心转换字符是(@),这个单一字符用作标记-代码的转换字符,有时也反过来用作代码-标记的转换字符。

这里一共有两种基本类型的转换:代码表达式和代码快。

<h1>Listing @items.Length items.</h1>

表达式@items.Length是作为隐式表达式来求解的,然后输出表达式的值3。这里不需要指出代码表达式的结束位置。

但是Razor自动从代码转回标记的能力,也带来了二义性的问题:

 @{
string rootNamespace = "MyApp";
}
<span>@rootNamespace.Models</span>

这个示例想要的输出结果是:  <span>MyApp.Models</span>  ,然而实际会出现错误,提示string没有Models属性,此时需要通过圆括号解决:

1 @{
2 string rootNamespace = "MyApp";
3 }
4 <span>@(rootNamespace).Models</span>

这样可以告诉Razor,.Models是字面量文本,而不是代码表达式的一部分。

对于电子邮件地址时的情况,Razor可以辨别出邮件的模式,进而不处理这种形式的表达式:

<span>support@megacorp.com</span>

但是如果确实想将这种形式的字符串作为一个表达式,也需要合理用圆括号:

对于

<li>Item_@item.Length</li>

期望的输出结果是<li>Item_3</li>,但是Razor会将其按照字符串进行打印。

处理的方法是:

<li>Item_@(item.Length)</li>

有时也需要使用@符号来进行转义:

 <p>
You should follow
@@aspnet
</p>

3.Razor语法示例

常见用途下的Razor语法;

  • 隐式代码表达式

代码表达式将被计算并将值写入到响应中,这就是视图中显示值的一般原理。

<span>@model.Message</span>
  • 显示代码表达式

代码表达式的值将被计算并写入到响应中,这就是在视图中显示值的一般原理

<span>1 + 2 = @(1 +2 )</span>
  • 无编码代码表达式

有些情况下,需要显式的渲染一些不应该采用HTML编码的值,这时可以采用Html.Raw方法来保证该值不被编码

<span>@Html.Raw(model.Message)</span>
  • 代码块

不像代码表达式先求的表达式的值,然后再输出到响应,代码块是简单地执行代码部分

 @{
int x = ;
string y = "because."
}
  • 文本和标记相结合

这个例子显示了在Razor中混用文本和标记的概念,具体如下:

 @foreach (var item in items)
{
<span>Item @item.Name.</span>
}
  • 混合代码和纯文本

Razor查找标签的开始位置以确定何时将代码转换为标记。然而,有时可能想在一个代码块之后立即输出纯文本。例如,在下面的这个例子中就是展示如何在一个条件语句块中显示纯文本

 @if (showMessage)
{
<text>this is plain text</text>
}

或者

 @if (showMessage)
{
@:this is plain text.
}

第一种使用<text>标签,这样只是把标签内容写入到响应中,而标签本身则不写入。第二种方式使用一种特殊的语法,实现代码到纯文本的转换,但是这种方法每次只能作用于一行文本。

  • 转义代码分隔符

可使用“@@”来编码“@”以达到显示“@”的目的。此外,时钟都可以选择使用HTML编码来实现。

Razor:

the asp.net twitter handle is @aspnet

或者

the asp.net twitter handle is @@aspnet
  • 代码注释
 @*
代码块
*@

4.布局

Razor的布局有助于使应用程序的多个视图保持一致的外观。可以使用布局为网站定义公共模版(或只是其中的一部分)。公公模版包含一个或多个占位符,应用程序中的其他视图为它们提供内容。从某些角度看,布局很像视图的抽象基类。如下则是一个简单的布局:

 <!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>
</head>
<body>
<h1>@ViewBag.Title</h1>
<div id="main-content">@RenderBody()</div>
<footer>@RenderSection("Footer")</footer>
</body>
</html>

对应视图的代码如下:

 1 @{
2 Layout = "~Views/Shared/SiteLayout.cshtml";
3 ViewBag.Title = "The Index";
4 }
5
6 <p>this is the main content!</p>
7
8 @section Footer{
9 this is the <strong>footer</strong>.
10 }

@section语法为布局中定义的一个节指定了内容。

默认情况下,视图必须为布局中定义的每一个节提供内容。如果向当前的布局中添加一个新节时,会使得引用该布局的每一个视图都不能正常运行。

但是,RenderSection方法有一个重载版本,允许指定不需要的节。可以给required参数传递一个false值来标记Footer节是可选的。

<footer>@RenderSection("Footer", required: false)</footer>

有时也在视图中定义一些默认内容

 <footer>
@if (IsSectionDefined("Footer"))
{
RenderSection("Footer");
}
else
{
<span>this is the default footer</span>
}
</footer>

5.ViewStart

在创建一个默认的ASP.NET MVC项目后,会在Views目录下自动添加一个_ViewStart.cshtml文件,它指定了一个默认布局

 @{
Layout = "~/Views/Shared/_Layout.cshtml"
}

如果多个视图都使用都使用同一个布局,就会产生冗余。_ViewStart.cshtml中的代码先于任何视图运行,所以一个视图可以重写Layout属性的默认值,从而重新选择了一个不同的布局。如果一组视图拥有共同的设置,那么_ViewStart.cshtml中的代码可以用来对共同的视图进行统一配置。如果有视图需要覆盖统一的设置,只需要修改对应的属性值即可。

6.指定部分视图

除了返回视图之外,操作方法也可以通过PartialView方法以PartialViewResult的形式返回部分视图:

 public class HomeController : HomeController
{
public ActionResult Message()
{
ViewBag.Message = "this is a partial view.";
return PartialView();
}
}

这种情形下,渲染的是视图Message.cshtml,但是如果布局是由_ViewStart.cshtml页面指定(而不是直接在视图中)的,将无法渲染布局。

除了不能指定布局之外,部分视图看起来和正常视图没有分别:

<h2>@ViewBag.Message</h2>

在使用Ajax技术进行更新时,部分视图是很有用的。示例使用jQuery将一个部分视图的内容加载到一个使用了Ajax调用的当前视图中:

 <div id="result"></div>
@section scripts{
<script type="text/javascript">
$(function(){
$('#result').load('/home/message');
});
</script>
}

代码使用jQuery的load方法向Message操作方法发出一个Ajax请求,而后使用请求的结果更新id属性值为result的DIV元素。

ASP.NET MVC5高级编程 之 视图的更多相关文章

  1. ASP&period;NET MVC5 高级编程 第3章 视图

    参考资料<ASP.NET MVC5 高级编程>第5版 第3章 视图 3.1 视图的作用 视图的职责是向用户提供界面. 不像基于文件的框架,ASP.NET Web Forms 和PHP ,视 ...

  2. ASP&period;NET MVC5 高级编程 第5章 表单和HTML辅助方法

    参考资料<ASP.NET MVC5 高级编程>第5版 第5章 表单和HTML辅助方法 5.1 表单的使用 5.1.1 action 和 method 特性 默认情况下,表单发送的是 HTT ...

  3. ASP&period;NET MVC5 高级编程 第2章 控制器

    参考资料<ASP.NET MVC5 高级编程>第5版 第2章 控制器 控制器:响应用户的HTTP 请求,并将处理的信息返回给浏览器. 2.1 ASP.NET MVC 简介 MVC 模式中的 ...

  4. ASP&period;NET MVC5 高级编程-学习日记-第一章 入门

    1.1 ASP.NET MVC 简介 ASP.NET是一种构建Web应用程序的框架,它将一般的MVC(Model-View-Controller)模式应用于ASP.NET框架. 1.1.1 MVC模式 ...

  5. ASP&period;NET MVC5高级编程 之 模型

    1. 为MVC Music Store建模 Models文件夹(右击) --> 添加 --> 类 为类添加对应的属性: public class Album { public virtua ...

  6. ASP&period;NET MVC5 高级编程-学习日记-第三章 视图

    开发人员之所以花费大量时间来重点设计控制器和模型对象,是因为在这些领域中,精心编写的整洁代码是开发一个可维护Web应用程序的基础. 3.1 视图的作用 视图的职责是向用户提供用户界面.当控制器针对被请 ...

  7. ASP&period;NET MVC5高级编程 之 Ajax

    jQuery不仅支持所有现代浏览器,包括IE.Firefox.Safari.Opera和Chrome等,还可以在编写代码和浏览器API冲突时隐藏不一致性(和错误). 1. jQuery jQuery擅 ...

  8. 学习《ASP&period;NET MVC5高级编程》——基架

    基架--代码生成的模板.我姑且这么去定义它,在我学习微软向编程之前从未听说过,比如php代码,大部分情况下是我用vim去手写而成,重复使用的代码需要复制粘贴,即使后来我在使用eclipse这样的IDE ...

  9. ASP&period;NET MVC5高级编程 之 HTML辅助方法

    Html属性调用HTML辅助方法,Url属性调用URL辅助方法,Ajax属性调用Ajax辅助方法. HTML辅助方法 1.Html.BeginForm @using (Html.BeginForm(& ...

随机推荐

  1. Netty In Action

    1 introduction 1.2 Asynchronous by design two most common ways to work with or implement an asynchro ...

  2. czxt

    实验三 进程调度模拟程序 1.    目的和要求 1.1.           实验目的 用高级语言完成一个进程调度程序,以加深对进程的概念及进程调度算法的理解. 1.2.           实验要 ...

  3. 实现checkbox组件化&lpar;Component&rpar;

    之前我写了一篇自定义checkbox的文章,通过css3实现自定义的checkbox,并没有使用当今流行的Reactjs, 或者Vuejs之类的进行组件化.但是很显然,这样封装的checkbox组件复 ...

  4. Latex 笔记

    A source file is made up of text, formulas, and instructions (commands) to $\LaTeX.$ Commands start ...

  5. scala言语基础学习二

    使用yield和函数式编程转化数组 算法案例(移除第一个负数之后的所有负数) 改良高校方案

  6. openlayers加载百度地图

    最近在做openlayers添加百度地图的扩展类,经过轮番的尝试,终于将其接入了,但是发现偏差比较大,有根据百度的坐标进行了比对,将切片原点进行了调整,发现OK了.打开百度地图,可以看出切片的路径如: ...

  7. MIPI D-PHY 总结

    Operating Modes: Control, High-Speed, and Escape 1.The Lane is only in High-Speed mode during Data b ...

  8. Apache Commons Pool2 源码分析 &vert; Apache Commons Pool2 Source Code Analysis

    Apache Commons Pool实现了对象池的功能.定义了对象的生成.销毁.激活.钝化等操作及其状态转换,并提供几个默认的对象池实现.在讲述其实现原理前,先提一下其中有几个重要的对象: Pool ...

  9. linux下64位汇编的系统调用&lpar;5&rpar;

    看到这里大家都基本知道了如何进行linux下的汇编系统调用:不过有些童鞋可能会问:那些C库中函数里为我们解决的额外汇编代码你是怎么知道的? 好吧,我承认:我是通过逆向知道的,这貌似有点犯规的嫌疑- 比 ...

  10. GIT 数据结构

    Git doesn’t think of or store its data this way. Instead, Git thinks of its data more like a series ...