1. 程式人生 > >ASP.NET MVC 3.0 Razor檢視如何展示多實體

ASP.NET MVC 3.0 Razor檢視如何展示多實體



Razor檢視模型支援@model來初始化頁面物件型別,比如:

1     @model FlashTravel.Models.Traveller>

也可以是一個支援迭代的公開列舉器:

1     @model IEnumerable<FlashTravel.Models.Traveller>

當我們只關注對一個實體類進行呈現時,MVC 3.0的實現非常給力,Controller層只需要兩行程式碼:

public ActionResult Index()

{

    var traveller = dbFlashTravel.Traveller.ToList();

    return View(traveller);

}

ToList()方法返回的是List<T>集合,它實現(Implements)了介面IEnumerable<out T>,所以var型變數traveller被傳遞到View層時,可採用foreach進行遍歷:

  @foreach (var item in Model) {

    //......

}

 

    再強大的框架,也只是把簡單的事變得更簡單,而問題一旦稍變複雜,多半都要靠聰明的大腦來解決,我挺喜歡去42區逛,其首頁的類似微博的即時資訊功能挺有意思;好歹自己也是做BS開發的,於是就採用MVC 3.0模擬一個玩玩。

    其業務模型大概可以這樣描述:已登入會員可以發表一條碎碎念(文字限定142),與之相隨的圖片數量不限定(測試時只提供一張),同時可以被別的會員回覆。從該描述中提取出最基本的實體物件:會員(Traveller)、碎碎念(Chat)、碎碎念圖片(ChatImage)、碎碎念回覆(ChatReply)

來自VS2010的免費圖片:

imageimageimage image   

 

很明顯,實體Chat的主鍵欄位ChatID關聯起了實體ChatImage(1對多)和實體ChatReply(1對多)。

Linq to SQL該ORM框架會自動把資料庫表一一對映為同名實體類(EF4.0道理亦然),這些實體類就像築造樓房的磚瓦一樣,成為各種業務模型組裝的最為基本的物件。基於上述分析,顯然發表碎碎念這一業務模型有三個最基本的實體類參與:Chat、ChatImage、ChatReply,為了更好地表述他們,我將該業務模型命名為ChatIntegration(碎碎念綜合),並採用一個檢視模型模式(ViewModel Pattern)類來進行封裝:

namespace FlashTravel.ViewModels

{

    /// <summary>

    /// 碎碎念綜合

    /// </summary>

    public class ChatIntegration

    {

        /// <summary>

        /// 碎碎念

        /// </summary>

        public Chat ChatHeader { set; get; }

 

        /// <summary>

        /// 碎碎念圖片

        /// </summary>

        public IList<ChatImage> ChatImages { set; get; }

 

        /// <summary>

        /// 碎碎念回覆

        /// </summary>

        public IList<ChatReply> ChatReplys { set; get; }

    }

}

上述程式碼表明,單個碎碎念業務模型包含著一個碎碎念主體叫ChatHeader,和若干圖片(複數),以及若干回覆(複數)。

 

一般來講,Model層在專案中往往就是起到一個承上啟下的作用(MVC或傳統的三層),如同小學時老師教我們八股式的寫作文一般:先開頭,接著鋪述一段,然後作一個承上啟下的段落,隨之進入下一段的描寫,最後以一個總結段結尾。這裡的業務模型(ChatIntegration)同理:第一段,在Controller層先撈取資料庫中的資料(基於Linq to SQL)將其儲存在業務模型中;第二段,業務模型將被拋給View層的頁面,通過Razor引擎遍歷呈現。

 

如前所述,接下來會做兩件事:先往下層看,瞧一下處於中間的業務模型(ChatIntegration)是如何得到資料庫資料;然後再擡頭仰視,看看業務模型(ChatIntegration)被拋給View後如何遍歷資料。

(一.)往下層看,按MVC 3.0的"分離關注點"思想,對於訪問資料庫的程式碼應該採用Repository設計模式,使得Controller層中的Action僅需呼叫Repository層中的相關函式就可得到資料集,從而很順暢地將函式返回值傳給View層,雖然"約定大於配置"很重要,但只要我的精簡尚未破壞MVC架構,姑且就"耦合"一下吧,我會把訪問資料庫的程式碼直接寫在名為Index的Action中:

public class ChatController : Controller

{

    FlashTravelDataContext dbFlashTravel = new FlashTravelDataContext();

 

    public ActionResult Index()

    {

        //查詢所有碎碎念

        var chatIntegrationList = from chat in dbFlashTravel.Chat 

                                  join chatImage in dbFlashTravel.ChatImage

                                   

                                  on chat.ChatID equals chatImage.ChatID into chatImages

                                  join chatReply in dbFlashTravel.ChatReply

                                   

                                  on chat.ChatID equals chatReply.ChatID into chatReplys

                                  select new ChatIntegration

                                  {

                                      ChatHeader = chat,

                                      ChatImages = chatImages.ToList(),

                                      ChatReplys = chatReplys.ToList()

                                  };

        return View(chatIntegrationList);

    }

}

通過宣告式的Linq查詢,我們得到了目前資料庫中所有的碎碎念記錄(實際中想必要根據時間進行過濾[比如只查詢最近一週]、並分頁呈現,這裡都忽略),沒有更多的程式碼了。大家會看到在基於內聯接的Linq查詢的後半段,可直接定義(select new ChatIntegation)每一個碎碎念模型中的屬性值。只要搞定一個ChatIntegation的賦值,那麼基於泛型集合的chatIntegrationList都會統統受到影響,最終它作為View(object model)的引數傳給檢視層。

 

(二.)擡頭仰視,檢視層會接受到我們載著滿滿資料的業務模型集合(ChatIntegation泛型集合):

1     @model IEnumerable<FlashTravel.ViewModels.ChatIntegration>

    接下來,業務模型ChatIntegation集合至少需要一次foreach遍歷,用以將每一個ChatIntegation提取出來作進一步處理。就像我們在Controller層對資料作組裝一樣,只要對一個業務模型進行編碼,那麼基於泛型集合的每一個元素都會受到影響。

    顯然,第一次的遍歷會在每個一個元素ChatIntegation中取到三個屬性:ChatHeader(碎碎念)、ChatImages(圖片)、ChatReplys(回覆),

發現圖片和回覆分別又是一個新的子泛型集合,於是對他們二位再分別作第二層foreach遍歷:  @{

    ViewBag.Title = "Index";

}

<h2>

    Index</h2>

<p>

    @Html.ActionLink("Create New", "Create")

</p>

<table>

    @foreach (var item in Model)

    {        

        <tr>

            <td style="width: 150px; text-align: center;">

                @item.ChatHeader.NickName

            </td>

            <td style="width: 350px; text-align: right;">

                @item.ChatHeader.PublishTime

            </td>

        </tr>

        <tr>

            <td style="width: 150px; text-align: center;">

                @foreach (var image in item.ChatImages)

                {

                    <img alt="@image.ImageRemark" src="@image.ImageUrl" /> 

                }

            </td>

            <td style="width: 350px; text-align: left;">

                @item.ChatHeader.Content

            </td>

        </tr>

         

        <tr>

            <td colspan="2">

                <br />

                <span style="font-weight: bold;">FeedBack</span>

                <hr />

            </td>

        </tr>

         

           foreach (var reply in item.ChatReplys)

           {

        <tr>

            <td colspan="2">

                <table style="width: 100%;">

                    <tr>

                        <td>

                            @reply.PublishTime|@reply.NickName

                        </td>

                    </tr>

                    <tr>

                        <td>

                            @reply.Reply

                        </td>

                    </tr>

                </table>

            </td>

        </tr>

           }

    }

</table>

 

最後呈現的效果便是:

一個Demo下來,真正需要手寫的程式碼仍不足50行,程式設計方式的理解還是最為重要

摘自 不覺流年似水

http://www.2cto.com/kf/201112/113058.html