天天看點

返璞歸真 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>

                <a href="Category" target="_blank">Demo</a>

        </p>

                1、<a href="Category/Create" target="_blank">通過 DataAnnotations 實作資料驗證;對用戶端驗證的支援</a>

                2、<a href="AsynchronousController" target="_blank">對異步 Controller 的支援</a>

                3、MVC 與 Dynamic Data 的結合

                <br />

                <a href="Category/Edit/21" target="_blank">實作 Model 級别的 Dynamic Data</a>

                <a href="Category/Edit2/21" target="_blank">實作 Property 級别的 Dynamic Data</a>

                新增了對模闆的支援(模闆源自 Dynamic Data)

ActionResult View() ActionResult View(int id, [DefaultValue(1)]int page) { }

                5、關于路由的新特性,參看:http://webabcd.blog.51cto.com/1787395/341124

                6、Html.Hidden() 增強 - 其可以用于儲存二進制(Binary 類型或 byte[] 類型)資料

                比如:

                <%= Html.Hidden("Photo", Model.Photo) %>

                生成的 html 為:

                <input type="hidden" name="Photo" value="QVNQLk5FVCBNVkMgaXMgZnVuIQ................................." />

                7、在 VS 2010 中增加了 asp.net mvc 相關的代碼片段

                組合鍵 ctrl+k ctrl+b 調出代碼片段管理器後檢視

                8、新增了一個名為 RequireHttpsAttribute 的 Action Filter - 其作用就是用于隻允許 HTTPS 請求。預設情況下,如果是 HTTP 請求,則會自動跳轉到 HTTPS 請求

                9、隻有 HTTP POST 請求才能傳回 JsonResult    

                10、新增了 HttpPostAttribute HttpPutAttribute HttpGetAttribute HttpDeleteAttribute ,以前是類似這樣寫的 AcceptVerbs(HttpVerbs.Post)

                11、UrlParameter.Optional - 如果從url路由中無法擷取某個參數的值,則從url參數中擷取該參數的值。示例如下

                routes.MapRoute(

                        "Default",

                        "{controller}/{action}/{id}",

                        new { controller = "Home", action = "Index", id = UrlParameter.Optional }

                );

                <a href="Category/?pageIndex=0" target="_blank">使用 UrlParameter.Optional 的一個示範</a>

                12、對 Area 的支援 - 允許在一個應用程式記憶體在多套 MVC,在項目中單擊右鍵 -> Add -> Area...(詳見示例程式中的 Areas 目錄)

                13、新增的一些幫助方法

                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()

                它們主要用于實作 Scaffold,以及為 Property 或 Model 指定顯示模闆或編輯模闆

</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

                // 開始一個異步操作

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>

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,就一定要配置路由的命名空間

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.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);

4、對 DataAnnotations 的支援,實作資料驗證(包括用戶端驗證)

Metadata.cs

* ASP.NET MVC 2.0 - 對 DataAnnotations 的支援,可以實作驗證及 Scaffold

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 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)

                        return View("Edit2", category);

                // 用于示範實作 Property 級别的 Dynamic Data

ActionResult Edit2() ActionResult Edit2(int id, FormCollection formValues)

ActionResult Details() ActionResult Details(int id)

                        return View("Details", category);

ActionResult Create() ActionResult Create()

                        ProductCategory category = new ProductCategory()

                        };

                        return View(category);

                // 用于示範通過 DataAnnotations 實作資料驗證

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>" %>

        Create

        <!--

                為了實作用戶端驗證,需要引用以下兩個 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, "*") %>

                                <%: Html.LabelFor(model => model.ParentProductCategoryID) %>

                                <%: Html.TextBoxFor(model => model.ParentProductCategoryID) %>

                                <%: Html.ValidationMessageFor(model => model.ParentProductCategoryID) %>

                                <%: Html.LabelFor(model => model.Name) %>

                                <%: Html.TextBoxFor(model => model.Name) %>

                                <%: Html.ValidationMessageFor(model => model.Name) %>

                                <%: Html.LabelFor(model => model.rowguid) %>

                                <%: Html.TextBoxFor(model => model.rowguid) %>

                                <%: Html.ValidationMessageFor(model => model.rowguid) %>

                                <%: Html.LabelFor(model => model.ModifiedDate) %>

                                <%: Html.TextBox("ModifiedDate", DateTime.Now.ToString("yyyy-MM-dd")) %>

                                <%: Html.ValidationMessageFor(model => model.ModifiedDate) %>

                        <p>

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

                        </p>

                </fieldset>

        <% } %>

                <%: Html.ActionLink("Back to List", "Index") %>

5、MVC 與 Dynamic Data 相結合的 Demo

相關的 DataAnnotations 就用上面的那個

Category/Edit.aspx

        Edit

        <h2>

                Edit</h2>

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

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

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

Category/Edit2.aspx

        Edit2

        <h2>Edit2</h2>

                        <%= Html.LabelFor(c => c.ParentProductCategoryID) %>: <%= Html.EditorFor(c => c.ParentProductCategoryID)%>

                        </br>

                        <%= Html.LabelFor(c => c.Name) %>: <%= Html.EditorFor(c => c.Name)%>

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

Category/Index.aspx

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

        Index

                Index</h2>

        <table>

                <tr>

                        <th>

                        </th>

                                ProductCategoryID

                                ParentProductCategoryID

                                名稱

                                rowguid

                                ModifiedDate

                </tr>

                <% foreach (var item in Model)

                     { %>

                        <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>

                                <%: item.ProductCategoryID %>

                                <%: item.ParentProductCategoryID %>

                                <%: Html.DisplayTextFor(c => item.Name)%>

                                <%: item.rowguid %>

                                        Html.DisplayFor() - 可以指定顯示模闆(可以指定 Property 級模闆,也可以指定 Model 級模闆),本例的模闆位址為 Views/Shared/DisplayTemplates/MyDate.ascx ,這種實作方式來自 Dynamic Data

                                <%= Html.DisplayFor(Product => item.ModifiedDate, "MyDate")%>

                <% } %>

        </table>

                <%= Html.RouteLink("上一頁", "Default", new { pageIndex = Convert.ToInt32(Request.QueryString["pageIndex"] ?? "2") - 1 })%>

                |

                <%= Html.RouteLink("下一頁", "Default", new { pageIndex = Convert.ToInt32(Request.QueryString["pageIndex"] ?? "2") + 1 })%>

                <%: Html.ActionLink("Create New", "Create") %>

Shared/DisplayTemplates/MyDate.ascx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>

<%= Html.Encode(String.Format("{0:yyyy-MM-dd}", Model)) %>

OK

[×××]

繼續閱讀