• MVC自学系列之三(MVC视图Views)


      View的约定

    1.根据约定,Views目录下包含着每一个与Controller同名但是没有像Controller后缀的文件夹;因此对于控制器HomeController就对应在views目录下有个目录名为Home;

    2.对于controller目录,在每个对应的View下都有若干个与controller内方法同名的view文件。这样view就与action方法有了基本的关联。

      ViewData与ViewBag

    1.从技术上讲,数据通过叫做ViewData的特殊集合类ViewDataDictionary来从controller传递到views的;

    ex:ViewData[“CurrentTime”] = DateTime.Now;

    2.ViewBag是对ViewData的一种动态封装,它可以像以下那样赋值;

    ex:ViewBag.CurrentTime = DateTime.Now;

    3.在对ViewBag与ViewData的选择上,实际上没有选择哪一个是最好,因为,ViewBag只是对于ViewData的语法糖,它们从技术的优越性上讲是一致的;这可以根据个人习惯而选择。

    4.它们之间的不同

    ①ViewBag的关键字必须是有效的C#标示符,例如你可以把一个值放到ViewData[“Key With Spaces”],但是ViewBag要是用这样的关键字就无法通过编译

    ②动态的值不能被作为参数传递到扩展方法中去,C#编译器必须知道每一个参数的类型。

    所以这中情况下就应该使用像ViewData[“Name”]或是(String)View.Name的方式

      强类型视图

    1.在你的Controller中,代码可能如下:

     
    public ActionResult List() {
     var albums = new List<Album>();
     for(int i = 0; i < 10; i++) {
       albums.Add(new Album {Title = "Product " + i});
     }
     ViewBag.Albums = albums;
     return View();
    }
    而在View中
    <ul>
    @foreach (Album a in (ViewBag.Albums as IEnumerable<Album>)) {
     <li>@a.Title</li>
    }
    </ul>
    2.在Controller,你也可以不用ViewBag,而直接返回一个集合实体给View,这时就得添加引用了
    ex:return View(albums)
    而在View中,你只需要标记一下刚才传过来的实体类型,就可直接使用Model了
    @model IEnumerable<MvcApplication1.Models.Album> 
    @foreach (Album p in Model) { 
    <li>@p.Title</li> 
    }

    或者使用using的方式

    @using MvcApplication1.Models 
    @model IEnumerable<Album> 
    <ul> 
    @foreach (Album p in Model) { 
    <li>@p.Title</li> 
    } 
    </ul>
    在web.config文件中直接添加引用
    <pages pageBaseType="System.Web.Mvc.WebViewPage"> 
       <namespaces> 
         <add namespace="System.Web.Mvc" /> 
         <add namespace="System.Web.Mvc.Ajax" /> 
         <add namespace="System.Web.Mvc.Html" /> 
         <add namespace="System.Web.Routing" /> 
         <add namespace="MvcApplication1.Models" /> 
       </namespaces> 
    </pages>

      视图模型

    1.问题:当一个视图需要展示不同的数据,而这些数据并不直接来自于一个领域模型

    2.解决:

    ①一种方法就是把一些额外数据放入到ViewBag中去

    ②当你想要控制数据在View的流动时,你就需要强类型来更好的利用智能提示。①的方法就不好,这就该我们的视图模型登场了,这个视图模型包含了你想要在View展示的所有信息。

     

      Razor视图引擎

    1.提供一种干净、轻量级、简单的视图引擎,它并不包含像Web Forms视图引擎那样的不整齐的句法。
    2.提供了流畅的句法,把语法结构和额外特性压缩到最小,在你和你的视图标记之间尽可能的提供最少的句法,在代码和html标签中尽可能得提供平滑的过度。
    ex:
    @{ 
    var items = new string[] {"one", "two", "three"}; 
    } 
    <html> 
    <head><title>Sample View</title></head> 
    <body> 
    <h1>Listing @items.Length items.</h1> 
    <ul> 
    @foreach(var item in items) { 
       <li>The item name is @item.</li> 
    }
    
    </ul></html>

    3.语法

    在Razor中的关键转义字符就是@,@用来从代码到标记的转化。

    @{
       string rootNamespace = "MyApp";
    }
    <span>@rootNamespace.Models</span>
    我们希望得到的是MyApp类下的Models属性值,结果却得到了(由于Razor认为@rootNamespace是代码表达式)
    <span>MyApp.Models</span>
    这时我们可以用括号来表达明确的含义
    <span>@(rootNamespace).Models</span>
    ②对email的智能过滤,对于像
    <span>support@megacorp.com</span>
    Razor可以识别这种e-mail格式,并且不会把@megacorp.com当做有效的代码表达式
    ③括号的用途:在Razor当有语意不明确时,就用括号来让Razor明白你的意图。
     

    特性

    1.HTML的封装

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

    类似于这种XSS恶意代码,Razor会直接渲染为封装过后的HTML代码,而不是去执行那些javascript代码;


    ②如果需要输出HTML标记,你要返回一个System.Web.IHtmlString的实例,这时Razor不会去封装它;你可以创建HtmlString的实例或者使用Html.Raw这个方便的方法。

    ③HTML的自动封装对于XSS有很好的减轻作用,但是并不满足用户输入javascript的情况,

    ex:

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

    此时如果用户输入的用户名为:\x3cscript\x3e%20alert(\x27pwnd\x27)%20\x3c/script\x3e;

    那么就会解析script标签从而对系统造成安全隐患。我们应该用@Ajax.JavaScriptStringEncode 来封装用户的输入

    2.代码块

    @foreach(var item in stuff) {<li>The item name is @item.</li>}

    Razor理解HTML标记的结构,当<li>标签关闭时,它能够自动转换为代码,我们不需要来再用大括号来声明<li>便签的结束。

    3.注释

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

    4.布局

    ①我们先写一个母版页

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

    它看起来像普通的Razor页面,但是预留了一个@RenderBody的占位符

    ②接下来我们就可以套用所写的母版页了

    @{
       Layout = "~/Views/Shared/SiteLayout.cshtml";
       View.Title = "The Index!";
    }
    <p>This is the main content!</p>
    为母版页加入底部模块:<footer>@RenderSection("Footer")</footer>
    <!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>

    这时,之前的子页会抛出异常,因为所有使用了母版页的子页都需要定义Footer这部分,

    @section Footer {
        This is the <strong>footer</strong>.
    }

    ③ViewStart

    所有的子页都采用一个模板页会很枯燥并且难于维护,

    每一个View的子目录下都会有一个_ViewStart.Cshtml页,它可以解决这种枯燥,这个页面的代码总是在相同的目录下先执行,并且这个原理适用于所有的子目录。

    为易维护、易扩展、易复用、灵活多样而努力~~
  • 相关阅读:
    设计模式
    显示WiFi密码
    05-变量
    04-杂谈
    03-杂谈
    02-杂谈
    01-linux介绍、命令
    14-python--inner
    13-python--bibao
    11-python-iterator
  • 原文地址:https://www.cnblogs.com/SpringDays/p/3235199.html
Copyright © 2020-2023  润新知