zoukankan      html  css  js  c++  java
  • MVC3

    摘要:

    • 视图的作用
    • 如何指定视图
    • 强类型视图
    • 理解视图模型
    • 如何添加视图
    • Razor的使用方法
    • 如何指定分部视图
    • 理解视图引擎

    1.视图的作用

    在ASP.NET MVC中向用户提供用户界面的过程由两部分组成

    • 检查由控制器提交的ViewDataDictionary(通过ViewData属性访问)
    • 将其内容转换为HTML格式

    并非所有的视图都将渲染HTML格式,视图也可以渲染其它类型的内容。


    从ASP.NET MVC3开始,视图数据可以通过ViewBag属性访问。ViewBag属性是动态的,可以通过ViewData属性访问的相同数据。

    ViewBag.Message等同于ViewData["Message"],但彼此之间并不存在真正的技术优势。

    但二者差异:

    • 当要访问的关键字是一个有效的C#标识符时,ViewBag才起作用。如,在ViewData["Key With Spaces"]中存放一个值,那么将不能使用ViewBag访问这个值
    • 这个动态的值不能作为一个参数传递给扩展的方法。因为编译器为了选择正确的扩展方法,在编译时必须知道每一个参数的真正类型。如,@Html.TextBox("name",ViewBag.Name)将编译失败,需显式转换

    <body>
        <h1>@ViewBag.Message</h1>
        <p>...</p>
    </body>

    视图并不像ASP.NET Web Forms和PHP,它本身不会被直接访问,浏览器不能指向一个视图并渲染它。

    然而,视图总是被一个控制器渲染,该控制器向它提供了要渲染的数据。

    2.指定视图

    • 每个控制器在Views目录下都有一个对应的文件夹,其名称与控制器一样。
    • 每一个控制器的View文件夹中,每一个操作方法都有一个名称相同的视图文件与之相对应。操作方法通过View方法返回ViewResult对象。如,
    •  return View();
    • 当控制器操作没有指定视图的名称时,操作方法返回的ViewResult将按照约定来确定视图(先在目录/Views/ControllerName下查找与控制器名称(不带Controller)相同的视图)。与APS.NET MVC的大部分约定设置一样,这一约定是可以重写的,指定不同视图(可以指定完全位于不同目录结构的视图)如,
    • return View("NotIndex");
      return View("~/View/Example/Index.cshtml");//避开视图引擎的内部查找机制,需使用文件扩展名

    3.强类型视图

    创建Album实例列表并在视图中迭代它们:

    public  ActionResult List()
    {
        var albums = new List<Albums>();
        for(int i = 0;i<10;i++)
        {
            albums.Add(new Albums{Title = "Product" + i });
        }
        ViewBag.Albums = albums;
        return View();
    }
    
    //视图
    <ul>
    @foreach(Album a in (ViewBag.Albums as IEnumerable<Album>))
    {
        <li>@a.Title</li>
    }
    </ul>
    View Code

    在枚举之前需将动态的ViewBag.Albums转换为IEnumerable<Album>类型,也可以使用dynamic使代码更整洁,但这样不能使用代码智能感知

    <ul>
    @foreach(dynamic p in ViewBag.Albums)
    {
        <li>@p.Title</li>
    }
    </ul>

    在Controller方法中,可以通过向重载的View方法中传递模型实例来指定模型,在后台传进View方法的值将赋值给ViewData.Model属性,如

    return View(albums);

    接下来,告知视图哪种类型的模式正在使用@model声明,注意需输入完全限定类型名,如

    @model IEnumerable<MvcApplication1.Models.Album>
    <ul>
    @foreach(Album p in Model){
        <li>@p.Title</li>
    </ul>

    如果不像输入模型类型的完全限定类型名,可以使用@using关键字声明,如

    @using MvcApplication1.Models
    @model IEnumerable<Album>

    对于在视图中经常使用的名称空间,比较好的方法是在Views目录下的web.config文件中声明,如

    @using MvcApplication1.Models
    <system.web.webPages.razor>
        ...
        <pages pageBaseType="System.Web.Mvc.WebViewPage">
            <namespaces>
                <add namespace="System.Web.Mvc" />
                ...
                <add namespace="MvcApplication1.Models />
                ...
            </namespaces>
        <pages>
    </system.web.webPages.razor>

    4.视图模型

    视图通常需要显示没有直接映射到域模型的数据,当需要显示与视图主模型无关的额外数据时:

    • 把数据存放ViewBag属性(优点:方便使用  缺点:如果严格控制流进视图的数据,就必须使所有类型都是强数据的,以便利用智能感知)
    • 编写自定义的视图模型类

     如创建购物车汇总页面:

    public class ShoppingCartViewModel{
        public IEnumerable<Product> Products{get;set;}
        public decimal CartTotal{get;set;}
        public string Message{get;set;}
    }
    
    //输入视图
    @model ShoppingCartSummaryViewModel

    5.添加视图及自定义T4视图模板(后者需上机测试,不理解

    6.Razor视图引擎

    Razor提供了一个干净、轻量级、简单的视图引擎,不包含原有的Web Forms视图引擎中包含的“语法累赘”。最大限度地减少了语法和额外的字符。

    代码表达式

    Razor中的核心转换字符是@,用作标记-代码的转换字符,有时也反过来用作代码-标记的转换字符。这里一共有两种基本类型的转换:代码表达式和代码块

    WebForm视图只支持显式代码表达式,而ASP.NET MVC支持隐式代码表达式求解。

    <h1>Listing @stuff.Length items.</h1>//ASP.NET MVC
    <h1>Listing <%:@stuff.Length %>items.</h1>//WEB Form

     Razor十分智能,可以知道表达式后面的空格不是一个有效的标识符,所以可以顺畅地转回到标记语言。

    下面的情况也可以准确的推断,自动从代码转回标记:

    <ul>
    @foreach(var item in items){
        <li>The item name is @item.</li>//Razor可以知道@item后的字符不是引用属性或方法,因为它看到在.后是尖括号
    }
    </ul>

     但下面的情况会出现潜在的二义性,想要的输出结果是<span>MyApp.Models</span>,但系统会提示string没有Models属性:

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

    解决这种问题可以将表达式用圆括号括起来以支持显式代码表达式:

    <span>@(rootNamespace).Models</span>

    Razor足够智能,可以辨别出电子地址的一般模式,而不会处理这种形式的表达式。(内部采用了一个简单的算法,即采用@@符号转义一个@符号)

    但当遇到向将这种形式字符串作为表达式时,需用圆括号指明,如

    <li>Item_@item.Length</li>//这种情况下会匹配成邮件地址
    <li>Item_@(item.Length)</li>//解决

    当需要显示一些以@符号开头的语句时,Razor会先尝试解析这些隐式代码表达式,失败后使用@@来转义@符号

    Html编码:

    Razor表达式时用Html编码的

    如果想展示Html标记,就返回一个System.Web.IHtmlString对象的实例,Razor并不对它进行编码。也可以创建一个HtmlString实例或者使用Html.Raw便捷方法。如

    //将不会弹出警告,而会显示出编码信息
    @{    string message = "<script>alert('haacked!');</script>";
    }
    <span>@message</span>
    
    //将显示不经过Html编码的消息
    @{    string message = "<strong>This is bold!</strong>";
    }
    <span>Html.Raw(@message)</span>

    但在JS中,仅仅是HTML编码是不够的,还需要使用@Ajax.JavaScriptStringEncode方法对用户输入进行编码,避免XSS攻击。如

    <script>
        $(function(){
            var message = 'Hello @ViewBag.Username';
            ...
    </script>
    
    //需修改为
    <script>
        $(function(){
            var message = 'Hello @Ajax.JavaScriptStringEncode(@ViewBag.Username)');
            ...
    </script>

    代码块

    Razor理解HTML标记语言的结构,可以自动转换代码。但相比之下,WebForm视图引擎就需要显式支出代码和标记之间转换的代码。如

    @foreach(var item in stuff){
        <li>The item name is @item.</li>
    }
    
    //Web Form视图引擎
    <% foreach(var item in stuff){ %>
        <li>The item name is <%: item %>.</li>
    <% } %>

    代码块除了需要@符号分割之外还需要使用花括号,如

    @{
        string是= “...”;
        ViewBag.Title " Another line of code";
    }
    //
    @{Html.RenderPartial("SomePartial");}

    注意:代码块中的语句(如foreach循环和if代码块中的语句)是不需要使用花括号的。

    Razor语法示例

    a.隐式代码表达式:Razor中的隐式代码表达式总是采用HTML编码方式。

    //Razor
    <span>@model.Message</span>
    //Web Forms
    <span><%:model.Message %></span>

    b.显示代码表达式:

    //Razor
    <span>ISBN@(isbn)</span>
    //Web Forms
    <span>ISBN<%: isbn %></span

    c.无编码代码表达式:

    //Razor
    <span>@Html.Raw(model.Message)</span>
    //Web Forms
    <span><%:Html.Raw(model.Message) %></span>

    d.代码块:

    不像代码表达式先求得表达式的值,然后再输出到响应,代码块是简单的执行代码的部分,对于声明以后要使用的变量是有用的

    //Razor
    @{
        int x = 123;
        string y = "because";
    }
    //Web Forms
    <%
        int x = 123;
        string y = "because";
    %>

    e.文本和标记相结合:

    //Razor
    @foreach(var item in items){
        <span>The item name is @item.Name.</span>
    }
    //Web Form
    <% foreach(var item in items){ %>
        <span>Item <%: item.Name %>.</span>
    <% } %>

    f.混合代码和纯文本:Razor查找标签的开始位置以确定何时将代码转换为标记

    //Razor
    @if(showMessage){
        <text>This is plain text</text>
    }
    或
    @if(showMessage){
        @:This is plain text.
    }
    //Web Form
    <% if(showMessage) {%>
        This is plain text.
    <% } %>

    g.转义代码分隔符:可以用“@@”来编码“@”达到显示的目的。

    //Razor
    My Twitter Handle is &#64;hacked
    或
    My Twitter Handle is @@hacked
    //Web Form
    &lt;% express %&gt;marks a code nugget.

    h.服务器端的注释:

    //Razor
    @*
    This is a multiline server side comment.
    @if(showMessage){
        <h1>@ViewBag.Message</h1>
    }
    ALL of this is commented out.
    *@
    //Web Form
    <%--
    This is a multiline server side comment.
    <% if(showMessage) {%>
        <h1><%: ViewBag.Message %></h1>
    <% } %>
    All of this is commented out.
    --%>

    i.调用泛型方法:需整个表达式用圆括号括起来,因为调用泛型方法的代码包含尖括号,尖括号会导致Razor转回标记

    //Razor
    @(Html.SomeMethod<AType>())
    //Web Form
    <%: Html.SomeMethod<AType>() %>

    布局

    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>
    
    
    //定义
    @{
        Layout = "~</Views/Shared/SiteLayout.cshtml";
        View.Title = "The Index!";
    }
    <p>This is the main content!</p>    
    
    @section Footer{
        This is the <strong>footer</strong>
    }
    View Code

     渲染出的内容:

    <!DOCTYPE html>
    <html>
    <head><title>The Index!</title></head>
    <body>
        <h1>The Index!</h1>
        <div id="main-content"><p>This is  the main content!></p></div>
        <footer>This is the <strong> footer</strong></footer>
    </body>
    </html>

     RenderSection方法有一个重载版本,运行指定不需要的节。

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

    也可以通过以下方式来定义默认值

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

    ViewStart

    消除冗余的视图布局指定代码。

    _ViewStart.cshtml的文件代码先于任何视图运行,所以一个视图可以重写Layout属性的默认值,从而重新选择一个不同的布局。

    但如果一组视图拥有共同的设置,那么可以在这个文件中统一设置。

    7.指定分部视图

    操作方法可以通过PartialView方法以PartialViewResult的形式返回分部视图。如,

    return PartialView();

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

    分部分视图在使用AJAX技术进行部分更新的情形中是有用的。

    8.视图引擎

    ASP.NET MVC的生命周期

    HTTP请求—路由—控制器—视图结果—视图引擎—视图—响应

    9.配置视图引擎

    视图引擎配置在文件Global.asax.cs

    在Application_Start方法中编写代码替代默认视图引擎

    protected void Application_Start(){
        ViewEngines.Engines.Clear();
        ViewEngines.Engines.Add(new MyViewEngine());
        RegisterRoutes(RouteTable.Routes);
    }

    创建自定义视图引擎时,需要实现IViewEngine接口和IView接口(此部分内容较多,参考59~63页

  • 相关阅读:
    mysql,windows自动备份设置
    彻底搞清楚javascript中的require、import和export
    Spring Boot 打包报错Failed to execute goal org.apache.maven.plugins:mavenresourcesplugin:3.2.0
    Spring AOP 切点切面
    12.5M 30M 90M DEM免费下载!【转】
    JS 中的数组遍历方式效率比较[转]
    cesium加载CAD模型(.dwg)
    Cesium发布下一代3D Tiles规范预览
    cesium点击面高亮事件[转]
    MySQL 5.7及8.0版本数据库的root密码遗忘的解决办法
  • 原文地址:https://www.cnblogs.com/KevinG/p/3560658.html
Copyright © 2011-2022 走看看