• 返璞归真 asp.net mvc (4) View/ViewEngine


    [索引页]
    [源码下载]


    返璞归真 asp.net mvc (4) - View/ViewEngine


    作者:webabcd


    介绍
    asp.net mvc 之 View 和 ViewEngine
    • ViewData 和 TempData 都可以向 View 传递数据,其中 TempData 是保存在 Session 中的,一次请求后此 Session 会被清除
    • HtmlHelper - 在 View 中显示 HTML 元素的一个帮助类
    • IViewEngine - 自定义的视图引擎需要实现此接口
    • VirtualPathProviderViewEngine - 实现了 IViewEngine 接口的抽象类,实现了根据指定的路径格式搜索对应的页面文件的功能(内用缓存机制)
    • IView - 只有一个需要实现的方法,就是呈现 HTML 结果


    示例
    1、演示 View 的 Demo
    ViewDemoController.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Mvc.Ajax;

    using MVC.Models;

    namespace MVC.Controllers
    {
        
    public class ViewDemoController : Controller
        
    {
            ProductSystem ps 
    = new ProductSystem();

            
    public ActionResult Details(int id)
            
    {
                var product 
    = ps.GetProduct(id);

                
    if (product == null)
                
    {
                    
    return View("NotFound");
                }

                
    else
                
    {
                    product.CategoriesReference.Load();

                    
    // 编辑 Product 的时候需要在一个 DropDownList 中选择其所对应的 Category, 所以这里要构造一个 SelectList 类型的 ViewData
                    if (product.Categories == null)
                        ViewData[
    "CategoryList"= new SelectList(new CategeorySystem().GetCategory(), "CategoryId""CategoryName");
                    
    else
                        ViewData[
    "CategoryList"= new SelectList(new CategeorySystem().GetCategory(), "CategoryId""CategoryName", product.Categories.CategoryID);

                    
    // ViewData 和 TempData 都可以向 View 传递数据,其中 TempData 是保存在 Session 中的,一次请求后此 Session 会被清除
                    
    // 在 View 中使用的时候,ViewData[key] 或 TempData[key] 即可
                    TempData["Temp"= "TempData";

                    
    return View("Details", product);
                }

            }


            [AcceptVerbs(HttpVerbs.Post)]
            
    public ActionResult Update(int id, FormCollection formValues)
            
    {
                var product 
    = ps.GetProduct(id);

                
    // 可以通过 UpdateModel, 让系统自动为属性赋值(通过反射的方式,取得对象的属性名称,然后和 Request 的 key 做匹配,匹配成功的则赋值)
                UpdateModel<Products>(product);

                
    // 通过以下的方式让 UpdateModel 只更新指定属性
                
    // string[] allowedProperties = new[] { "ProductName", "UnitPrice" };
                
    // UpdateModel(product, allowedProperties);

                var category 
    = new CategeorySystem().GetCategory(int.Parse(Request.Form["Category"]));
                product.CategoriesReference.EntityKey 
    = ps.CreateEntityKey("Categories", category);

                
    if (!product.IsValid)
                
    {
                    
    foreach (var validation in product.GetValidation())
                    
    {
                        
    // 设置验证信息
                        ModelState.AddModelError(validation.PropertyName, validation.ErrorMessage);
                    }

                }

                
    else
                
    {
                    ps.Save();
                }


                ViewData[
    "CategoryList"= new SelectList(new CategeorySystem().GetCategory(), "CategoryId""CategoryName", category.CategoryID);

                
    return View("Details", product);
            }

        }

    }

    Details.aspx
    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC.Models.Products>" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Details
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        
    <style type="text/css">
            .bold
            
    {
                font-weight
    : bold;
            
    }

        
    </style>
        
    <h2>
            Details
    </h2>
        
    <%= Html.ValidationSummary("输入信息有误"%>
        
    <% Html.BeginForm("Update""ViewDemo"new { id = Model.ProductID }, FormMethod.Post); %>
        
    <p>
            
    <strong>ProductID:</strong>
            
    <%= Html.Encode(Model.ProductID) %>
        
    </p>
        
    <p>
            
    <label for="ProductName">
                ProductName:
    </label>
            
    <%= Html.TextBox("ProductName", Model.ProductName, new { style = "color: blue;", @class = "bold" })%>
            
    <%= Html.ValidationMessage("ProductName""*"%>
        
    </p>
        
    <p>
            
    <label for="Category">
                Category:
    </label>
            
    <%-- Html.ListBox() 和 Html.DropDownList() 需要 IEnumerable<SelectListItem> 类型的数据做数据源 --%>
            
    <%= Html.DropDownList("Category", ViewData["CategoryList"as SelectList)%>
        
    </p>
        
    <p>
            
    <strong>UnitPrice:</strong>
            
    <%= Html.Encode(string.Format("{0:F2}", Model.UnitPrice))%>
        
    </p>
        
    <p>
            
    <input type="submit" value="Save" />
        
    </p>
        
    <p>
            
    <%= TempData["Temp"]%>
        
    </p>
        
    <% Html.EndForm(); %>
        
    <p>
            
    <%=Html.RouteLink("返回首页"new { Controller = "Home" })%>
        
    </p>

        
    <%-- 需要使用 Web Form 方式的话,则在后置代码中继承 System.Web.Mvc.ViewPage 或 System.Web.Mvc.ViewPage<T> 即可-- %>
        
        
    <%-- 
    HtmlHelper 简要说明:


    可以用如下的方式生成 form
    using (Html.BeginForm()) { }
    using (Html.BeginRouteForm()) { }
    Html.BeginForm(); Html.EndForm();


    可以使用 Html.ListBox(), Html.RadioButton() 之类的来生成 html 元素


    Html.ValidationMessage() 
    - 指定的 ModelName 输入信息不合法时所输出的验证信息
    Html.ValidationSummary() 
    - 汇总所有验证信息
    验证信息可以在 Action 中用 ModelState.AddModelError() 的方式来添加
    验证信息的样式通过样式表修改 .field
    -validation-error{} .input-validation-error {} .validation-summary-errors {}


    Html.Encode(); Html.AttributeEncode(); 用于对输出的内容做编码


    Html.RenderPartial() 
    - 引入一个 Partial View


    Html.ActionLink() 
    - 根据 Action 找目标
    Html.RouteLink() 
    - 根据路由找目标


    Html.ViewContext 
    - View 的上下文信息。包括 Controller, TempData, ViewData, 路由信息, HttpContext 等信息
    --
    %>
    </asp:Content>


    2、创建一个自定义的 ViewEngine 的 Demo
    MyView.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    using System.Web.Mvc;
    using System.IO;
    using System.Text.RegularExpressions;

    namespace MVC
    {
        
    /// <summary>
        
    /// 自定义的视图
        
    /// 视图需要继承 IView 接口
        
    /// </summary>

        public class MyView : IView
        
    {
            
    // 视图文件的物理路径
            private string _viewPhysicalPath;

            
    public MyView(string viewPhysicalPath)
            
    {
                _viewPhysicalPath 
    = viewPhysicalPath;
            }


            
    /// <summary>
            
    /// 实现 IView 接口的 Render() 方法
            
    /// </summary>

            public void Render(ViewContext viewContext, TextWriter writer)
            
    {
                
    // 获取视图文件的原始内容  
                string rawContents = File.ReadAllText(_viewPhysicalPath);

                
    // 根据自定义的规则解析原始内容  
                string parsedContents = Parse(rawContents, viewContext.ViewData);

                
    // 呈现出解析后的内容
                writer.Write(parsedContents);
            }



            
    public string Parse(string contents, ViewDataDictionary viewData)
            
    {
                
    // 对 {##} 之间的内容作解析
                return Regex.Replace
                (
                    contents, 
                    
    @"\{#(.+)#\}"

                    
    // 委托类型 public delegate string MatchEvaluator(Match match)
                    p => GetMatch(p, viewData)
                );
            }


            
    protected virtual string GetMatch(Match m, ViewDataDictionary viewData)
            
    {
                
    if (m.Success)
                
    {
                    
    // 获取匹配后的结果,即 ViewData 中的 key 值,并根据这个 key 值返回 ViewData 中对应的 value
                    string key = m.Result("$1");
                    
    if (viewData.ContainsKey(key))
                    
    {
                        
    return viewData[key].ToString();
                    }

                }


                
    return string.Empty;
            }

        }

    }


    MyViewEngine.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    using System.Web.Mvc;

    namespace MVC
    {
        
    // MvcContrib 中提供了很多 ViewEngine, 还提供了以 asp.net mvc 框架为基础的一些额外的功能
        
    // 地址:http://www.codeplex.com/MVCContrib

        
    /// <summary>
        
    /// 自定义的视图引擎
        
    /// 视图引擎需要继承 IViewEngine 接口
        
    /// VirtualPathProviderViewEngine 继承了 IViewEngine 接口,实现了根据指定的路径格式搜索对应的页面文件的功能(内用缓存机制)
        
    /// </summary>

        public class MyViewEngine : VirtualPathProviderViewEngine
        
    {
            
    public MyViewEngine()
            
    {
                
    // 自定义 View 路径格式
                base.ViewLocationFormats = new string[] 
                

                    
    "~/Views/{1}/{0}.my""~/Views/Shared/{0}.my" 
                }
    ;
            }


            
    protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
            
    {
                
    return this.CreateView(controllerContext, partialPath, string.Empty);
            }


            
    /// <summary>
            
    /// 根据指定路径返回一个实现了 IView 接口的对象
            
    /// </summary>

            protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
            
    {
                var physicalPath 
    = controllerContext.HttpContext.Server.MapPath(viewPath);

                
    return new MyView(physicalPath);
            }

        }

    }


    Global.asax.cs
    protected void Application_Start()
    {
        
    // 增加新的视图引擎 ViewEngine
        ViewEngines.Engines.Add(new MyViewEngine());  
    }

    CustomViewEngineController.cs
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Mvc.Ajax;

    namespace MVC.Controllers
    {
        
    /// <summary>
        
    /// 用于演示自定义的 ViewEngine 的 Controller
        
    /// </summary>

        public class CustomViewEngineController : Controller
        
    {
            
    public ActionResult Index()
            
    {
                ViewData[
    "name"= "webabcd";
                ViewData[
    "age"= "70";

                
    // 如果视图文件中有 {##} 形式的字符串,则 MyViewEngine 会对其做相应的解析
                
    // 如 {#name#} 会被解析为 webabcd

                
    return View();
            }
      
        }

    }


    Index.my(智能感知在“工具 - 选项 - 文本编辑器 - 文件扩展名”中编辑)
    <html>
    <head>
        
    <title>创建自定义的 ViewEngine 的 Demo</title>
    </head>
    <body>
        
    <div>name: {#name#}</div>
        
    <div>age: {#age#}</div>
    </body>
    </html>

    运行结果:
    name: webabcd
    age: 70


    OK
    [源码下载]
  • 相关阅读:
    学习Python的体会 (1)
    李敖的管理经
    《inside the c++ object model》读书笔记 之五 构造,解构,拷贝语意学
    《inside the c++ object model》读书笔记 之四 Function 语意学
    《inside the c++ object model》读书笔记 之三:Data语意学
    《inside the c++ object model》读书笔记 之六 执行期语意学
    排序算法插入排序/冒泡排序
    《inside the c++ object model》读书笔记 之七 站在对象模型的尖端
    《inside the c++ object model》读书笔记 之二:构造函数
    《inside the c++ object model》读书笔记 之一:对象
  • 原文地址:https://www.cnblogs.com/webabcd/p/1456453.html
Copyright © 2020-2023  润新知