ASP.NET MVC 3.0 Razor视图如何展示多实体

来源:未知 责任编辑:智问网络 发表时间:2013-10-22 19:24 点击:

 

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>

 

最后呈现的效果便是:

<script></script>

 

一个Demo下来,真正需要手写的代码仍不足50行,编程方式的理解还是最为重要

摘自 不觉流年似水

    发表评论
    请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
    用户名: 验证码:点击我更换图片
    最新评论 更多>>

    推荐热点

    • 浅析.NET下XML数据访问新机制
    • asp.net 面试+笔试题目第1/2页
    • C# 邮件地址是否合法的验证
    • C#高级编程:数据库连接[1]
    • asp.net 设置GridView的选中行的实现代码
    • 经典C++程序1
    • IIS 自动回收导致后台定时器失效的问题解决
    • ASP.NET&#160;GridView列表代码示例
    • 微软ASP.NET站点部署指南(3):使用Web.Config文件的Transforma
    网站首页 - 友情链接 - 网站地图 - TAG标签 - RSS订阅 - 内容搜索
    Copyright © 2008-2015 计算机技术学习交流网. 版权所有

    豫ICP备11007008号-1