• [.NET MVC进阶系列03] Views 视图基础


    [注:此文对应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代码:

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

       上面的代码中,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在SamplesAlbumList中,视图文件Albums.cshtml在ViewAlbums中

         对应的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类  

    1 public class ShoppingCartViewModle
    2 {
    3     public IEnumerable<Product> Products {get;set;}
    4     public decimal CartTotal {get; set;}
    5     public string Message {get;set;}          
    6 }

        这样,就可以把你需要的所有相关购物车的所有信息综合在一起传递给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(&#39;haacked!&#39;);&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)显示文本的@

         &#64; 或者 @@

        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

        

  • 相关阅读:
    Openflow1.3
    10行Python代码实现人脸定位
    Ubuntu安装Docker
    docker 命令部分
    tf.truncated_normal和tf.random_normal使用方法的区别
    Tensorboard服务激活
    Tensorflow基础
    TFRecords转化和读取
    卷积层+池化层的理解
    TensorFlow实现LeNet5模型
  • 原文地址:https://www.cnblogs.com/chutianshu1981/p/3171150.html
Copyright © 2020-2023  润新知