• 返璞归真 asp.net mvc (6) asp.net mvc 2.0 新特性


    [索引页]
    [源码下载]


    返璞归真 asp.net mvc (6) - asp.net mvc 2.0 新特性


    作者:webabcd


    介绍
    asp.net mvc 之 asp.net mvc 2.0 新特性:如通过 DataAnnotations 实现数据验证及客户端验证,MVC 与 Dynamic Data 的结合,对异步 Controller 的支持,对 Area 的支持,新增的一些帮助方法等


    示例
    1、新特性总结
    Index.aspx
    代码
    <%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Home Page
    </asp:Content>

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        
    <h2><%: ViewData["Message"%></h2>
        
    <p>
            
    <href="Category" target="_blank">Demo</a>
        
    </p>
        
    <p>
            1、
    <href="Category/Create" target="_blank">通过 DataAnnotations 实现数据验证;对客户端验证的支持</a>
        
    </p>
        
    <p>
            2、
    <href="AsynchronousController" target="_blank">对异步 Controller 的支持</a>
        
    </p>
        
    <p>
            3、MVC 与 Dynamic Data 的结合
            
    <br />
            
    <href="Category/Edit/21" target="_blank">实现 Model 级别的 Dynamic Data</a>
            
    <br />
            
    <href="Category/Edit2/21" target="_blank">实现 Property 级别的 Dynamic Data</a>
            
    <br />
            新增了对模板的支持(模板源自 Dynamic Data)
        
    </p>
        
    <p>
            4、新增的参数级的声明 DefaultValueAttribute - 用于为参数指定默认值public ActionResult View(int id, [DefaultValue(1)]int page) { }
        
    </p>
        
    <p>
            5、关于路由的新特性,参看:http://www.cnblogs.com/webabcd/archive/2010/05/20/1739750.html
        
    </p>
        
    <p>
            6、Html.Hidden() 增强 - 其可以用于保存二进制(Binary 类型或 byte[] 类型)数据
            
    <br />
            比如:
            
    <br />
            
    &lt;%= Html.Hidden("Photo", Model.Photo) %&gt;
            
    <br />
            生成的 html 为:
            
    <br />
            
    &lt;input type="hidden" name="Photo" value="QVNQLk5FVCBNVkMgaXMgZnVuIQ................................." /&gt;
        
    </p>
        
    <p>
            7、在 VS 2010 中增加了 asp.net mvc 相关的代码片段
            
    <br />
            组合键 ctrl+k ctrl+b 调出代码片段管理器后查看
        
    </p>
        
    <p>
            8、新增了一个名为 RequireHttpsAttribute 的 Action Filter - 其作用就是用于只允许 HTTPS 请求。默认情况下,如果是 HTTP 请求,则会自动跳转到 HTTPS 请求
        
    </p>
        
    <p>
            9、只有 HTTP POST 请求才能返回 JsonResult 
        
    </p>
        
    <p>
            10、新增了 HttpPostAttribute HttpPutAttribute HttpGetAttribute HttpDeleteAttribute ,以前是类似这样写的 AcceptVerbs(HttpVerbs.Post)
        
    </p>
        
    <p>
            11、UrlParameter.Optional - 如果从url路由中无法获取某个参数的值,则从url参数中获取该参数的值。示例如下
            
    <br />
            routes.MapRoute(
                "Default",
                "{controller}/{action}/{id}",
                new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
            
    <br />
            
    <href="Category/?pageIndex=0" target="_blank">使用 UrlParameter.Optional 的一个演示</a>
        
    </p>
        
    <p>
            12、对 Area 的支持 - 允许在一个应用程序内存在多套 MVC,在项目中单击右键 -> Add -> Area...(详见示例程序中的 Areas 目录)
        
    </p>
        
    <p>
            13、新增的一些帮助方法
            
    <br />
            Html.EditorFor(), Html.DisplayFor(), Html.DisplayTextFor(), Html.ValidationMessageFor(), Html.TextBoxFor(), Html.TextAreaFor(), Html.DropDownListFor(), Html.CheckboxFor(), Html.RadioButtonFor(), Html.ListBoxFor(), Html.PasswordFor(), Html.HiddenFor(), Html.LabelFor()
            
    <br />
            它们主要用于实现 Scaffold,以及为 Property 或 Model 指定显示模板或编辑模板
        
    </p>
    </asp:Content>


    2、异步 Controller 的 Demo
    Areas/AsynchronousController/Controllers/HomeController.cs
    代码
    /*
     * ASP.NET MVC 2.0 - 异步 Controller
     *     1、需要继承基类 AsyncController
     *     2、在 Async 为后缀的方法中写发起异步操作的逻辑;在 Completed 为后缀的方法中写异步操作完成后的逻辑;此两个方法的前缀就是这个异步 Controller 的 Action
     *     3、AsyncManager.OutstandingOperations.Increment() - 递增当前异步操作的计数器;AsyncManager.OutstandingOperations.Decrement(); - 递减当前异步操作的计数器。当异步操作的计数器为 0 时,则调用以 Completed 为后缀的方法
     *     4、AsyncManager.Parameters[key] - 传递指定参数到以 Completed 为后缀的方法中
     
    */

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;

    using System.Net;
    using System.Xml;
    using System.ServiceModel.Syndication;

    namespace MVC20.Areas.AsynchronousController.Controllers
    {
        [HandleError]
        
    public class HomeController : AsyncController
        {
            
    // IndexAsync() 以及 IndexCompleted() 是一对,其 Action 为 Index

            
    // 开始一个异步操作
            public void IndexAsync()
            {
                
    // 递增计数器
                AsyncManager.OutstandingOperations.Increment();

                HttpWebRequest request 
    = (HttpWebRequest)WebRequest.Create("http://www.cnblogs.com/webabcd/rss");
                request.BeginGetResponse(
    new AsyncCallback(OnGetRssFeedAsyncCompleted), request);
            }

            
    // 完成异步操作后
            public ActionResult IndexCompleted(IEnumerable<SyndicationItem> items)
            {
                ViewData[
    "Message"= "Welcome to ASP.NET MVC!";
                ViewData[
    "SyndicationItems"= items;
                
    return View();
            }

            
    private void OnGetRssFeedAsyncCompleted(IAsyncResult result)
            {
                HttpWebRequest request 
    = (HttpWebRequest)result.AsyncState;
                HttpWebResponse response 
    = (HttpWebResponse)request.EndGetResponse(result);

                
    using (XmlReader reader = XmlReader.Create(response.GetResponseStream()))
                {
                    SyndicationFeed feed 
    = SyndicationFeed.Load(reader);

                    
    // 传递指定参数到 IndexCompleted() 方法中
                    AsyncManager.Parameters["items"= feed.Items;

                    
    // 递减计数器,当计数器为 0 时,则调用 IndexCompleted()
                    AsyncManager.OutstandingOperations.Decrement();
                }
            }
        }
    }

    Areas/AsynchronousController/Views/Home/Index.aspx
    代码
    <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>

    <%@ Import Namespace="System.ServiceModel.Syndication" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        
    <title>Index</title>
    </head>
    <body>
        
    <div>
            
    <h2>
                
    <%: ViewData["Message"%></h2>
            
    <div>
                
    <!--
                    调用异步 Controller 的 Demo
                    注意:Inherits="System.Web.Mvc.ViewPage<dynamic>",这里用了 dynamic 类型
                
    -->
                
    <% foreach (SyndicationItem item in (IEnumerable<SyndicationItem>)ViewData["SyndicationItems"])
                   { 
    %>
                
    <href="<%= item.Id %>">
                    
    <%= item.Title.Text %></a><br />
                
    <% } %>
            
    </div>
        
    </div>
    </body>
    </html>


    3、Area 的 Demo
    Areas/AsynchronousController/AsynchronousControllerAreaRegistration.cs
    代码
    /*
     * ASP.NET MVC 2.0 - 对 Area 的支持,其允许在一个应用程序内实现多套 MVC
     *     1、新建 Area:右键 -> Add -> Area...
     *     2、继承 AreaRegistration,配置对应此 Area 的路由
     *     3、在 Global 中通过 AreaRegistration.RegisterAllAreas(); 注册此 Area
     *     4、有了 Area,就一定要配置路由的命名空间
     
    */

    using System.Web.Mvc;

    namespace MVC20.Areas.AsynchronousController
    {
        
    // 新建一个 Area 会自动生成这个继承自 AreaRegistration 的类
        
    // 如果需要使用此 Area 下的 MVC, 需要在 Global 中 AreaRegistration.RegisterAllAreas();
        public class AsynchronousControllerAreaRegistration : AreaRegistration
        {
            
    public override string AreaName
            {
                
    get
                {
                    
    return "AsynchronousController";
                }
            }

            
    public override void RegisterArea(AreaRegistrationContext context)
            {
                
    // 在 Area 中配置路由的时候,要设置命名空间(即本例中的第 4 个参数)
                context.MapRoute(
                    
    "AsynchronousController_default",
                    
    "AsynchronousController/{controller}/{action}/{id}",
                    
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
                    new string[] { "MVC20.Areas.AsynchronousController.Controllers" }
                );
            }
        }
    }

    Global.asax
    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;

    namespace MVC20
    {
        
    public class MvcApplication : System.Web.HttpApplication
        {
            
    public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute(
    "{resource}.axd/{*pathInfo}");

                
    // 用于本项目中使用了 Area,所以在配置路由的时候,要设置命名空间(即本例中的第 4 个参数)
                routes.MapRoute(
                    
    "Default"// Route name
                    "{controller}/{action}/{id}"// URL with parameters
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // UrlParameter.Optional - 如果从url路由中无法获取某个参数的值,则从url参数中获取该参数的值
                    new string[] {"MVC20.Controllers"}
                );
            }

            
    protected void Application_Start()
            {
                
    // 注册本应用程序中的所有 Area
                AreaRegistration.RegisterAllAreas();

                RegisterRoutes(RouteTable.Routes);
            }
        }
    }


    4、对 DataAnnotations 的支持,实现数据验证(包括客户端验证)
    Metadata.cs
    代码
    /*
     * ASP.NET MVC 2.0 - 对 DataAnnotations 的支持,可以实现验证及 Scaffold
     
    */

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

    using System.ComponentModel.DataAnnotations;

    namespace MVC20.Models
    {
        [MetadataType(
    typeof(ProductCategory_Metadata))]
        
    public partial class ProductCategory
        {

        }

        
    public class ProductCategory_Metadata
        {
            [Required(AllowEmptyStrings 
    = false, ErrorMessage = "{0} 为必填字段")]
            [NameValidation(ErrorMessage 
    = "{0} 只能是数字")]
            [Display(Name
    ="名称")]
            
    public string Name;

            [ScaffoldColumn(
    false)]
            
    public object ModifiedDate { getset; }

            
    // DisplayValue=true - 默认值。在显示模板中,用一个 lable 显示指定的值;在编辑模板中,用一个 lable 显示指定的值,并用一个 hidden input 保存该值
            
    // DisplayValue=false - 在显示模板中,不做任何显示;在编辑模板中,不做任何显示,但会用一个 hidden input 保存该值
            [System.Web.Mvc.HiddenInput(DisplayValue=true)]
            
    public object rowguid { getset; }
        }

        
    // 通过继承 RegularExpressionAttribute 实现自定义验证 Attribute
        
    // 通过继承 ValidationAttribute 实现自定义验证 Attribute 的 Demo 可以参看 http://www.cnblogs.com/webabcd/archive/2009/02/23/1396212.html
        public class NameValidationAttribute : RegularExpressionAttribute
        {
            
    public NameValidationAttribute()
                : 
    base("^[0-9]*$")
            {
     
            }
        }
    }

    CategoryController.cs
    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;

    using MVC20.Models;
    using System.ComponentModel;

    namespace MVC20.Controllers
    {
        
    public class CategoryController : Controller
        {
            
    // DefaultValueAttribute - 用于为参数指定默认值。当路由或url参数中无此参数时,则会使用此默认值
            public ActionResult Index([DefaultValue(2)]int pageIndex)
            {
                
    int pageSize = 10;
                var categories 
    = new Models.CategorySystem().GetCategory(pageIndex, pageSize);

                
    return View("Index", categories);
            }
            
            
    public ActionResult Edit(int id)
            {
                var category 
    = new Models.CategorySystem().GetCategory(id);

                
    return View("Edit", category);
            }

            
    // 用于演示实现 Model 级别的 Dynamic Data
            [HttpPost]
            
    public ActionResult Edit(int id, FormCollection formValues)
            {
                var cs 
    = new Models.CategorySystem();
                var category 
    = cs.GetCategory(id);

                TryUpdateModel
    <ProductCategory>(category);

                cs.Save();

                
    return RedirectToAction("Index");
            }

            
    public ActionResult Edit2(int id)
            {
                var category 
    = new Models.CategorySystem().GetCategory(id);

                
    return View("Edit2", category);
            }

            
    // 用于演示实现 Property 级别的 Dynamic Data
            [HttpPost]
            
    public ActionResult Edit2(int id, FormCollection formValues)
            {
                var cs 
    = new Models.CategorySystem();
                var category 
    = cs.GetCategory(id);

                TryUpdateModel
    <ProductCategory>(category);

                cs.Save();

                
    return RedirectToAction("Index");
            }

            
    public ActionResult Details(int id)
            {
                var category 
    = new Models.CategorySystem().GetCategory(id);

                
    return View("Details", category);
            }

            
    public ActionResult Create()
            {
                ProductCategory category 
    = new ProductCategory()
                {
                    
                };

                
    return View(category);
            }

            
    // 用于演示通过 DataAnnotations 实现数据验证
            [HttpPost]
            
    public ActionResult Create(ProductCategory category)
            {
                
    if (!ModelState.IsValid)
                {
                    
    return View(category);
                }
                
    else
                {
                    var cs 
    = new Models.CategorySystem();
                    cs.AddCategory(category);
                    cs.Save();

                    
    return View("Details", category);
                }
            }
        }
    }

    Create.aspx
    代码
    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC20.Models.ProductCategory>" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Create
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

        
    <!--
            为了实现客户端验证,需要引用以下两个 JavaScript
        
    -->
        
    <script src="http://www.cnblogs.com/Scripts/MicrosoftAjax.js" type="text/javascript"></script>
        
    <script src="http://www.cnblogs.com/Scripts/MicrosoftMvcValidation.js" type="text/javascript"></script>

        
    <h2>Create</h2>

        
    <!--启用客户端验证功能-->
        
    <% Html.EnableClientValidation(); %>

        
    <% using (Html.BeginForm()) {%>
      
            
    <!--  Html.ValidationSummary Helper Method Can Display Model-Level Errors -->
            
    <%: Html.ValidationSummary("错误信息如下:")%>

            
    <fieldset>
                
    <legend>Fields</legend>
                
                
    <div class="editor-label">
                    
    <%: Html.LabelFor(model => model.ProductCategoryID) %>
                
    </div>
                
    <div class="editor-field">
                    
    <%: Html.TextBoxFor(model => model.ProductCategoryID) %>
                    
    <!--
                        验证的错误信息来自 DataAnnotations,也可以通过 ValidationMessageFor() 来指定需要显示的错误信息
                    
    -->
                    
    <%: Html.ValidationMessageFor(model => model.ProductCategoryID, "*"%>
                
    </div>
                
                
    <div class="editor-label">
                    
    <%: Html.LabelFor(model => model.ParentProductCategoryID) %>
                
    </div>
                
    <div class="editor-field">
                    
    <%: Html.TextBoxFor(model => model.ParentProductCategoryID) %>
                    
    <%: Html.ValidationMessageFor(model => model.ParentProductCategoryID) %>
                
    </div>
                
                
    <div class="editor-label">
                    
    <%: Html.LabelFor(model => model.Name) %>
                
    </div>
                
    <div class="editor-field">
                    
    <%: Html.TextBoxFor(model => model.Name) %>
                    
    <%: Html.ValidationMessageFor(model => model.Name) %>
                
    </div>
                
                
    <div class="editor-label">
                    
    <%: Html.LabelFor(model => model.rowguid) %>
                
    </div>
                
    <div class="editor-field">
                    
    <%: Html.TextBoxFor(model => model.rowguid) %>
                    
    <%: Html.ValidationMessageFor(model => model.rowguid) %>
                
    </div>
                
                
    <div class="editor-label">
                    
    <%: Html.LabelFor(model => model.ModifiedDate) %>
                
    </div>
                
    <div class="editor-field">
                    
    <%: Html.TextBox("ModifiedDate", DateTime.Now.ToString("yyyy-MM-dd")) %>
                    
    <%: Html.ValidationMessageFor(model => model.ModifiedDate) %>
                
    </div>
                
                
    <p>
                    
    <input type="submit" value="Create" />
                
    </p>
            
    </fieldset>

        
    <% } %>

        
    <div>
            
    <%: Html.ActionLink("Back to List""Index"%>
        
    </div>

    </asp:Content>



    5、MVC 与 Dynamic Data 相结合的 Demo

    相关的 DataAnnotations 就用上面的那个

    Category/Edit.aspx
    代码
    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC20.Models.ProductCategory>" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Edit
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        
    <h2>
            Edit
    </h2>

        
    <% using (Html.BeginForm()) { %>

            
    <%: Html.ValidationSummary("错误信息如下:")%>

            
    <%= Html.EditorFor(category => category) %>

            
    <input type="submit" value="Save" />

        
    <% } %>

        
    <div>
            
    <%: Html.ActionLink("Back to List""Index"%>
        
    </div>
    </asp:Content>
     
    Category/Edit2.aspx
    代码
    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVC20.Models.ProductCategory>" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Edit2
    </asp:Content>

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

        
    <h2>Edit2</h2>

        
    <% using (Html.BeginForm()) {%>
        
            
    <%: Html.ValidationSummary("错误信息如下:")%>
                
            
    <fieldset>
                
    <legend>Fields</legend>
                
                
    <%= Html.LabelFor(c => c.ParentProductCategoryID) %><%= Html.EditorFor(c => c.ParentProductCategoryID)%>
                
    </br>
                
    <%= Html.LabelFor(c => c.Name) %><%= Html.EditorFor(c => c.Name)%>
                
                
    <p>
                    
    <input type="submit" value="Save" />
                
    </p>
            
    </fieldset>

        
    <% } %>

        
    <div>
            
    <%: Html.ActionLink("Back to List""Index"%>
        
    </div>

    </asp:Content>


    Category/Index.aspx
    代码
    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<MVC20.Models.ProductCategory>>" %>

    <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
        Index
    </asp:Content>
    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
        
    <h2>
            Index
    </h2>
        
    <table>
            
    <tr>
                
    <th>
                
    </th>
                
    <th>
                    ProductCategoryID
                
    </th>
                
    <th>
                    ParentProductCategoryID
                
    </th>
                
    <th>
                    名称
                
    </th>
                
    <th>
                    rowguid
                
    </th>
                
    <th>
                    ModifiedDate
                
    </th>
            
    </tr>
            
    <% foreach (var item in Model)
               { 
    %>
            
    <tr>
                
    <td>
                    
    <%: Html.ActionLink("Edit""Edit"new { id=item.ProductCategoryID }) %>
                    |
                    
    <%: Html.ActionLink("Details""Details"new { id=item.ProductCategoryID })%>
                    |
                    
    <%: Html.ActionLink("Delete""Delete"new { id=item.ProductCategoryID })%>
                
    </td>
                
    <td>
                    
    <%: item.ProductCategoryID %>
                
    </td>
                
    <td>
                    
    <%: item.ParentProductCategoryID %>
                
    </td>
                
    <td>
                    
    <%: Html.DisplayTextFor(c => item.Name)%>
                
    </td>
                
    <td>
                    
    <%: item.rowguid %>
                
    </td>
                
    <td>
                    
    <!--
                        Html.DisplayFor() - 可以指定显示模板(可以指定 Property 级模板,也可以指定 Model 级模板),本例的模板地址为 Views/Shared/DisplayTemplates/MyDate.ascx ,这种实现方式来自 Dynamic Data
                    
    -->
                    
    <%= Html.DisplayFor(Product => item.ModifiedDate, "MyDate")%>
                
    </td>
            
    </tr>
            
    <% } %>
        
    </table>
        
    <p>
            
    <%= Html.RouteLink("上一页""Default"new { pageIndex = Convert.ToInt32(Request.QueryString["pageIndex"] ?? "2"- 1 })%>
            |
            
    <%= Html.RouteLink("下一页""Default"new { pageIndex = Convert.ToInt32(Request.QueryString["pageIndex"] ?? "2"+ 1 })%>
        
    </p>
        
    <p>
            
    <%: Html.ActionLink("Create New""Create"%>
        
    </p>
    </asp:Content>


    Shared/DisplayTemplates/MyDate.ascx
    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
    <%= Html.Encode(String.Format("{0:yyyy-MM-dd}", Model)) %> 


    OK
    [源码下载]
  • 相关阅读:
    docker 部署 netcore3.1项目,使用nginx反向代理,swagger 不能访问的问题 SwaggerUIBundle is not defined
    windows 下使用SCP命令传递文件/文件夹到Liunx系统
    dockerfile 中的CMD 和 ENTRYPOINT 的区别
    netcore3.1 dockerfile 生成镜像 并 部署到 linux 系统
    docker 自定义网络 不使用 link 也能实现容器间网络互通
    CentOS 7中安装Nginx 并设置自启动
    微信小程序实现相册展示及图片预览
    netcore 3.1 项目部署到docker 及遇到的各种坑 和 对应解决方案
    netcore3.1 webApi项目发布Docker后,通过容器互联,访问redis 【部署redis到docker】
    docker 安装 mongodb 容器 及 挂载 配置文件、数据存放目录,日志存放目录,备份目录等
  • 原文地址:https://www.cnblogs.com/webabcd/p/1764150.html
Copyright © 2020-2023  润新知