[注:此文对应Chapter 3:Views]

  一、View的功能:

  1.View用来呈现页面UI,通过Controller来指定View:

   要注意的是,MVC和以前基于文件的Web应用不同,URL指向的并不是最终显示UI的文件,

     在MVC中,和URL打交道的是Controller,而不是View,是通过Controller中的Action Method来指定要显示的View

  2.Controller中指定View的规则:

在Controller中返回值类型为ActionResult的Action Method可以指定一个用来显示UI的View,

返回视图的代码:return View([参数]);

    返回View的View方法有三种不同参数,对应不同需求:

1)参数为空:return View()

    这种为最常用的格式,用来返回和Action方法名同名的默认视图;

2)参数为视图文件名:return View("HelloWorld.cshtml")

使用这种格式,可以将Action方法Url指向View/ControllName/HelloWorld.cshtml

    即,可以将Action方法Url指向View/ControllName下,和Action不同名的View文件

    3)参数为任意位置视图文件:return View("视图相对路径")

     在这种格式下,可以将Action方法对应的Url指向任意视图文件

   Controller代码:

 public class HomeController : Controller
{
public ActionResult Sample()
{
ViewBag.Message = "Hello World, this is a Sample!";
return View("~/Views/Shared/Error.cshtml");
}
}

   上面的代码中,HomeController的Action方法Sample(), 将Url: 域名/home/sample 指向了项目自动生成的Error视图

   运行程序得到的效果(注意地址):

   

   二、ViewData和ViewBag

    1.ViewData 

    原则上,controller中的数据是通过ViewDataDictionary(字典类)类的对象ViewData来传递给View 

    如:ViewData["CurrentTime"] = DataTime.Now;

    2.ViewBag

    从MVC3开始,将上面的语法进行简化,使用ViewBag动态包装ViewData,允许我们使用下面的语法:

      ViewBag.CurrentTime = DataTime.Now

    这种写法和上面的字典模式完全相同。

    注意:

    1)如果ViewBag.关键词其中的关键字中有空格,则不能编译通过;

    2)ViewBag不能直接作为动态参数进行传值

     如: @Html.TextBox("name",ViewBag.Name)——错误!

        @Html.TextBox("name",ViewData["Nmae"]) —— 正确!

        @Html.TextBox("name",(string)ViewBag.Name)——正确!

    

   三、基于强类型的View(Strongly Typed Views)

    1.原理:

    ViewData是ViewDataDictionary对象,该类不同于普通Dictionary类,其中包含了一个Model property,允许

    从Controller中,将一个(只能是一个)指定对象传到View中。

    这种方式不同于使用ViewBag,是强类型。不需要再进行类型指定,直接就可以使用该对象的属性和方法。

   2.使用:

    1)将要传到View中的对象作为参数给View()方法:

      如:return View(albums);

    2)在View中,用model接收该对象,直接包含新型信息,不需要再进行类型指定。

      @model IEnumerable<Album>

      <ul>

        @foreach(Album a in Model)

        { <li>@a.Title</li>}

      </ul>

     3.在View中添加命名空间引用

     1)直接在.cshtml文件中添加

      @using MvcMusicStore.Models

     2)在Views文件夹的web.config文件中添加,对整个Views文件夹中所有View都有效

      <pages pageBaseType="System.Web.Mvc.WebViewPage">

        <namespaces>

          。。。。

          <add namespace="MvcMusicStore.Models" />

        </namespaces>

      </pages>

    4.通过NuGet获取书籍配套例程代码:

     建好一个MVC4项目,【工具】——【库程序包管理器】——【程序包管理控制台】

     在命令行中键入:Install-Package Wrox.ProMvc4.Views.AlbumList

     

     这将添加两个文件夹到项目中,Album类和AlbumController在\Samples\AlbumList中,视图文件Albums.cshtml在\View\Albums中

     对应的URL为:域名/albums/listweaklytyped和域名/albums/liststronglytyped

     分别非强类型和强类型方式访问,可以通过代码比较其区别

    

    四、View Models

    1.起因——Conroller默认只能传递一个强类型对象到View中:

     1)ViewData所继承的ViewDataDictrionary类中,只能包含一个Model类,所以,每次只能从Controlller传到View一个对象。

     2)View中,大多数情况下需要多个后台传过来的对象来进行绑定显示或操作,单个后台穿过来的类对象不够用,而使用ViewBag

      的话,又失去了强类型的好处。

    2.解决方案:View Modles

      写自定义的View modle class,将你需要的所有信息都包含其中。

     如:自定义一个购物车Modle类  

 public class ShoppingCartViewModle
{
public IEnumerable<Product> Products {get;set;}
public decimal CartTotal {get; set;}
public string Message {get;set;}
}

    这样,就可以把你需要的所有相关购物车的所有信息综合在一起传递给View,并且使用的强类型View方式

    @model  ShoppingCartViewModel

    接收到的就是从Controller传过来的完整信息。

    3. 例子:

     建好一个MVC4项目,【工具】——【库程序包管理器】——【程序包管理控制台】

     在命令行中键入:Install-Package Wrox.ProMvc4.Views.ViewModel

    执行成功后,同上面的例子,会在项目中增加两个文件夹:

      /Samples/ShoppingCartViewModel  包含Product类、ShoppingCartViewModel类和控制器ShoppingCartController类

        /Views/ShoppingCart/ 包含对应的视图Index.cshtml

      

      运行后的效果(域名/ShoppingCart)

      

  

    五、Razor View Engine

    简单的介绍跳过去,直接写核心的

    1. 代码表达方式

    最重要的标示符在Razor中就是“@”

    1)代码表达式

     如 :@对象名.属性  ,等同于Web Form视图中的<%: 对象名.属性 %>

     *注:

       虽然Razor比较智能,能够判断大多数情况,自动判定到底是想要转换后台代码,还是直接显示,

        但也会遇到混淆的时候,可以通过下面几种方式来避免:

       A) @(后台代码)

        通过给后台代码加(),来强制将@要转换的内容,和其后面要直接显示的文本分开。

         B) @@将显示为@文本

      2)HTML编码(Html Encoding)

      为防止注入攻击,Razor表达式会自动进行HTML编码

      @{string message = "<script>alert('haacked!');</script>";}

      <span>@message</span>

      上面的HMTL View代码在运行时会被解释为:

      <span>&lt;script&gt;alert('haacked!');&lt;/script&gt;</span>

        这种HTML编码是自动进行的。

      在某些情况下,需要取消HTML编码,可以使用HtmlHelp,使用HtmlStirng对象或者Html.Raw()

      如:

        @{string message = "<strong>This is bold!</strong>";}

        <span>@Html.Raw(message)</span>

      这次,就不会再被转码,会直接显示为:

      <span><strong>This is bold!</strong></span>

      另外,使用@Ajax.JavaScriptStringEncode来编码和Javascript相关的用户输入,来防止注入攻击,如:

<script type="text/javascript">
    $(function () {
        var message = 'Hello @Ajax.JavaScriptStringEncode(ViewBag.Username)';
        $("#message").html(message).show('slow');
    });
</script>

      3)代码段:

       @{代码段}

     2. Razor 语法:

     1)隐式代码表达式:

      <span>@model.Message</span>

      又Razor自动判断后面的.Message是text文本还是model的property

     2)显示代码表达式:

      <span>@(model).Message</span>

      在括号中的是后台代码,其外的是文本

     3)不经Html转码的表达式:

      <span>@Html.Raw(model.Message)</span>

      前面提过,Razor为防止注入攻击,自动对用户输入进行HTML转码,如果特殊情况下不用转码,需要写成上面的格式

    4)代码段:

      @{

          int  x = 123;

          string y = "hello!";

       }

    5)混合文本和标签

      @foreach(var item in items)

      {

        <span> Item @item.Name.</span>

      }

    6)混合代码和文本

     @if(showMessage)

      {

        <text>This is plain text </text>

      }

      或

     @if(showMessage)

      {

        @:This is plain text.

      }

     注意,后面的语法@:只能针对一行代码

    7)显示文本的@

     @ 或者 @@

    8)服务器端注释:

     @*

      This is a multiline server side comment.
      @if (showMessage) {
        <h1>@ViewBag.Message</h1>
      }
      All of this is commented out.
     *@

    9)调用泛型函数(Generic Method)

     @(Html.SomeMethod<AType>()) 

     其实和显式的Razor代码表达式一样,注意外面加()!

    3. Layouts 布局

    类似于Asp.net中的MasterPage(母板页),用来设定统一外观的。

    设定整体布局使用的是~/_ViewStart.cshtml,它会在所有View被加载之前加载,指定母版布局视图

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

    每个View下Controller对应的文件夹中,可以添加自己的_ViewStart.cshtml,用来指定独自使用的布局视图,采取就近原则(替View代根目录中的);

    而且,Layout框架的赋值语句:Layout="。。。",也可以加到任意一个View文件中,作为此文件的单独布局框架。

    1)@RenderBody()

    Layout Template View中的@RenderBody()用于占位。

    2)@RenderSection()

    一个Layout可以包含多个分块(setions),例如,可以为Layout添加Footer分块

    <footer>@RenderSection("Footer")</footer>

    在使用这个Layout的View中,需要加入@section Footer{..}代码,来设置自己的footer,如:

    @section Footer{ @@Copyright 2001-2015, All Right Received. }

    但是,大多数时候,希望section都是可选的,可将其改为:

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

    更为通用的方式,是在设置可更改的Section时,配备一个默认的Section外观:

    <footer>

      @if (IsSctionDefined("Footer"))

      {

        RenderSection("Footer");

      }

      else

      {

        <span>This is the default footer. </span>

      }

    </footer>

    

    六、Patial View

    部分View是不包含layout的局部View。

    通常用来作为配合Ajax进行局部刷新。

    例子:

      Install-Package Wrox.ProMvc4.Views.SpecifyingViews

    

[.NET MVC进阶系列03] Views 视图基础的更多相关文章

  1. JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

    本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = ...

  2. [.NET MVC进阶系列0x] EF Code First 数据迁徙(Migrations)

    [因] Entity Framework中使用Code First模式进行开发时,数据库是基于Models中的类自动生成的(生成时间:第一次运行MVC项目时), 每次更改Models中类结构,重新编译 ...

  3. 【C#进阶系列】25 线程基础

    线程的概念 线程的职责是对CPU进行虚拟化. CPU为每个进程都提供了该进程专用的线程(功能相当于cpu),应用程序如果进入死循环,那么所处的进程会"冻结",但其他进程不会冻结,它 ...

  4. Java进阶知识03 Hibernate的基础配置详解

    1.Hibernate的原理/流程步骤 1.通过Configuration().configure(); 读取并解析hibernate.cfg.xml配置文件,并创建一个configuration对象 ...

  5. 【C#进阶系列】04 类型基础

    关于System.Object 所有类型都从System.Object派生而来. System.Object的公共方法中ToString()一般是返回对象的类型的全名,只有Int32这些类型将其重写后 ...

  6. C#进阶系列 ---- 《CLR via C#》

      [C#进阶系列]30 学习总结 [C#进阶系列]29 混合线程同步构造 [C#进阶系列]28 基元线程同步构造 [C#进阶系列]27 I/O限制的异步操作 [C#进阶系列]26 计算限制的异步操作 ...

  7. JavaScript进阶系列07,鼠标事件

    鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keyp ...

  8. JavaScript进阶系列06,事件委托

    在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个 ...

  9. JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

    本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 ■ 跨浏览器事件处理 □ 事件必须在页面元素加 ...

随机推荐

  1. A3992学习记录

    ATmega64+A3992驱动步进电机 //ATmega 64a 电机驱动板程序//编译环境 AVR Studio 4.17/AVR GCC//系统外部时钟16M//作者:虞恺 //日期:2012. ...

  2. Python生成验证码

    #!/usr/bin/env python #coding:utf8 import random #方法1: str_code='zxcvbnmasdfghjklqwertyuiopZXCVBNMAS ...

  3. Python入门二:函数

    一.函数的定义和使用 1.基本结构: def 函数名(参数): """ 文档字符串 """ 函数体 返回值 2.函数名: 和变量名命名规则一 ...

  4. 为cocos2d-x实现安卓输入框。非全屏,无dialog,绑定到lua

    cocos2d-x官方自带的输入框,简直惨不忍睹,在ios还好,在安卓简直了..用过的都知道... 所以为了用户体验,我们自己搞一个吧.输入框这种东西比较特殊,不像按钮.列表框之类的很容易实现,因为涉 ...

  5. EXTJS 3.0 资料 控件之 combo 用法

    EXTJS combo 控件: 1.先定义store //年款 var comboData_ReleasYear = [ ['], ['], ['], ['] ]; 2.定义combo控件 { lay ...

  6. resin access.log format配置详解

    The access log formatting variables follow the Apache variables:     %b result content length %D tim ...

  7. linux驱动系列之挂载(转)

    转自网页:http://www.cnblogs.com/yeahgis/archive/2012/04/05/2432779.html http://www.linuxso.com/command/c ...

  8. CSS定义字体间距 字体行与行间距

    CSS定义字体行间距 line-height:xxpx; CSS定义字体间距 下面我们讲述一下CSS的文本属性,还是先来看一下文本属性的详细列表: 属性     属性含义     属性值 Word-s ...

  9. vbe6ext.olb不能被加载 宏内存溢出

    今天想玩一下PowerPoint的宏,却发现玩不起来!!! 另外,每次打开ppt时都会提示vbe6ext.olb不能加载. 网上说重新下载个vbe6ext.olb然后复制到相应的路径.我也试着下载,然 ...

  10. bootstrap-treeview

    简要教程 bootstrap-treeview是一款效果非常酷的基于bootstrap的jQuery多级列表树插件.该jQuery插件基于Twitter Bootstrap,以简单和优雅的方式来显示一 ...