返璞歸真 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 的支持,新增的一些幫助方法等


示例
一、新特性總結
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>
                <a href= "Category" target= "_blank">Demo</a>
        </p>
        <p>
                一、<a href= "Category/Create" target= "_blank">經過 DataAnnotations 實現數據驗證;對客戶端驗證的支持</a>
        </p>
        <p>
                二、<a href= "AsynchronousController" target= "_blank">對異步 Controller 的支持</a>
        </p>
        <p>
                三、MVC 與 Dynamic Data 的結合
                <br />
                <a href= "Category/Edit/21" target= "_blank">實現 Model 級別的 Dynamic Data</a>
                <br />
                <a href= "Category/Edit2/21" target= "_blank">實現 Property 級別的 Dynamic Data</a>
                <br />
                新增了對模板的支持(模板源自 Dynamic Data)
        </p>
        <p>
ActionResult View() ActionResult View(int id, [DefaultValue(1)]int page) { }
        </p>
        <p>
                五、關於路由的新特性,參看:http://webabcd.blog.51cto.com/1787395/341124
        </p>
        <p>
                六、Html.Hidden() 加強 - 其能夠用於保存二進制(Binary 類型或 byte[] 類型)數據
                <br />
                好比:
                <br />
                <%= Html.Hidden( "Photo", Model.Photo) %>
                <br />
                生成的 html 爲:
                <br />
                <input type= "hidden" name= "Photo" value= "QVNQLk5FVCBNVkMgaXMgZnVuIQ................................." />
        </p>
        <p>
                七、在 VS 2010 中增長了 asp.net mvc 相關的代碼片斷
                <br />
                組合鍵 ctrl+k ctrl+b 調出代碼片斷管理器後查看
        </p>
        <p>
                八、新增了一個名爲 RequireHttpsAttribute 的 Action Filter - 其做用就是用於只容許 HTTPS 請求。默認狀況下,若是是 HTTP 請求,則會自動跳轉到 HTTPS 請求
        </p>
        <p>
                九、只有 HTTP POST 請求才能返回 JsonResult    
        </p>
        <p>
                十、新增了 HttpPostAttribute HttpPutAttribute HttpGetAttribute HttpDeleteAttribute ,之前是相似這樣寫的 AcceptVerbs(HttpVerbs.Post)
        </p>
        <p>
                十一、UrlParameter. Optional - 若是從url路由中沒法獲取某個參數的值,則從url參數中獲取該參數的值。示例以下
                <br />
                routes.MapRoute(
                         "Default",
                         "{controller}/{action}/{id}",
                         new { controller = "Home", action = "Index", id = UrlParameter. Optional }
                );
                <br />
                <a href= "Category/?pageIndex=0" target= "_blank">使用 UrlParameter. Optional 的一個演示</a>
        </p>
        <p>
                十二、對 Area 的支持 - 容許在一個應用程序內存在多套 MVC,在項目中單擊右鍵 -> Add -> Area...(詳見示例程序中的 Areas 目錄)
        </p>
        <p>
                1三、新增的一些幫助方法
                <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>
 
 
二、異步 Controller 的 Demo
Areas/AsynchronousController/Controllers/HomeController.cs
/*
* ASP.NET MVC 2.0 - 異步 Controller
*         一、須要繼承基類 AsyncController
*         二、在 Async 爲後綴的方法中寫發起異步操做的邏輯;在 Completed 爲後綴的方法中寫異步操做完成後的邏輯;此兩個方法的前綴就是這個異步 Controller 的 Action
*         三、AsyncManager.OutstandingOperations.Increment() - 遞增當前異步操做的計數器;AsyncManager.OutstandingOperations.Decrement(); - 遞減當前異步操做的計數器。當異步操做的計數器爲 0 時,則調用以 Completed 爲後綴的方法
*         四、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

                // 開始一個異步操做
void IndexAsync() void IndexAsync()
                {
                        // 遞增計數器
                        AsyncManager.OutstandingOperations.Increment();

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

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

void OnGetRssFeedAsyncCompleted() 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"])
                             { %>
                        <a href= "<%= item.Id %>">
                                <%= item.Title.Text %></a><br />
                        <% } %>
                </div>
        </div>
</body>
</html>
 
 
三、Area 的 Demo
Areas/AsynchronousController/AsynchronousControllerAreaRegistration.cs
/*
* ASP.NET MVC 2.0 - 對 Area 的支持,其容許在一個應用程序內實現多套 MVC
*         一、新建 Area:右鍵 -> Add -> Area...
*         二、繼承 AreaRegistration,配置對應此 Area 的路由
*         三、在 Global 中經過 AreaRegistration.RegisterAllAreas(); 註冊此 Area
*         四、有了 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";
                        }
                }

override void RegisterArea() 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
        {
static void RegisterRoutes() 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"}
                        );
                }

void Application_Start() void Application_Start()
                {
                        // 註冊本應用程序中的全部 Area
                        AreaRegistration.RegisterAllAreas();

                        RegisterRoutes(RouteTable.Routes);
                }
        }
}
 
 
四、對 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 { get; set; }

                // DisplayValue= true - 默認值。在顯示模板中,用一個 lable 顯示指定的值;在編輯模板中,用一個 lable 顯示指定的值,並用一個 hidden input 保存該值
                // DisplayValue= false - 在顯示模板中,不作任何顯示;在編輯模板中,不作任何顯示,但會用一個 hidden input 保存該值
                [System.Web.Mvc.HiddenInput(DisplayValue= true)]
                 public object rowguid { get; set; }
        }

        // 經過繼承 RegularExpressionAttribute 實現自定義驗證 Attribute
        // 經過繼承 ValidationAttribute 實現自定義驗證 Attribute 的 Demo 能夠參看 http://webabcd.blog.51cto.com/1787395/341156
         public class NameValidationAttribute : RegularExpressionAttribute
        {
NameValidationAttribute() 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參數中無此參數時,則會使用此默認值
ActionResult Index() ActionResult Index([DefaultValue(2)]int pageIndex)
                {
                        int pageSize = 10;
                        var categories = new Models.CategorySystem().GetCategory(pageIndex, pageSize);

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

                        return View( "Edit", category);
                }

                // 用於演示實現 Model 級別的 Dynamic Data
                [HttpPost]
ActionResult Edit() ActionResult Edit(int id, FormCollection formValues)
                {
                        var cs = new Models.CategorySystem();
                        var category = cs.GetCategory(id);

                        TryUpdateModel<ProductCategory>(category);

                        cs.Save();

                        return RedirectToAction( "Index");
                }

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

                        return View( "Edit2", category);
                }

                // 用於演示實現 Property 級別的 Dynamic Data
                [HttpPost]
ActionResult Edit2() ActionResult Edit2(int id, FormCollection formValues)
                {
                        var cs = new Models.CategorySystem();
                        var category = cs.GetCategory(id);

                        TryUpdateModel<ProductCategory>(category);

                        cs.Save();

                        return RedirectToAction( "Index");
                }

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

                        return View( "Details", category);
                }

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

                        return View(category);
                }

                // 用於演示經過 DataAnnotations 實現數據驗證
                [HttpPost]
ActionResult Create() 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>
 
 
五、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)) %>
 
 
相關文章
相關標籤/搜索