0

这必须非常简单,但我没有找到很多例子。我想获取所有带有相应标签的帖子并显示在视图中。基本上是一个简单的博客类型的东西。这是我的模型、视图模型、控制器和视图的代码。一切都可以减去标签,所以我的语法显然有问题。

public class MeWallPost
{
    public virtual int MeWallPostId { get; set; }

    public virtual string PostTitle { get; set; }        
    public virtual string PostContent { get; set; 
    public virtual DateTime PublishDate { get; set; }

    public virtual ICollection<MeWallPostMeTag> MeWallPostMeTags { get; set; }
}

public class MeTag
{
    public virtual int MeTagId { get; set; }

    public virtual string Name { get; set; }

    public virtual ICollection<MeWallPostMeTag> MeWallPostMeTags { get; set; }
}

public class MeWallPostMeTag
{
    [Key, Column(Order = 0)]
    public virtual int MeWallPostId { get; set; }
    [Key, Column(Order = 0)]
    public virtual int MeTagId { get; set; }

    public virtual MeWallPost MeWallPost { get; set; }
    public virtual MeTag MeTag { get; set; }
}

----

public class MeWallPostViewModel
{
    public string PostTitle { get; set; }
    public string PostContent { get; set; }
    public DateTime PublishDate { get; set; }

    private IEnumerable<MeTag> _Tags = new List<MeTag>();
    public IEnumerable<MeTag> Tags
    {
        get { return _Tags; }
        set { _Tags = value; }
    }

    public IEnumerable<MeWallPostViewModel> GetPosts()
    {
        var db = new DatselleDB();

        return from post in db.MeWallPosts             
               select new MeWallPostViewModel
               {
                   PostTitle = post.PostTitle,
                   PostContent = post.PostContent,
                   PublishDate = post.PublishDate,
                   Tags = post.MeWallPostMeTags.Select(a => a.MeTag)
               };
    }
}

-----

public ViewResult Index()
{
   return View(new MeWallPostViewModel());
}

------

@foreach (var item in Model.GetPosts()) {
<div class="postItem clear">
    <h3>@Html.DisplayFor(modelitem => item.PostTitle)</h3>
    <span class="date">@Html.DisplayFor(modelitem => item.PublishDate)</span>
    <p>@Html.DisplayFor(modelItem => item.PostContent)</p> 
    @foreach (var tag in Model.Tags) {
        @Html.DisplayFor(modelItem => tag.Name.ToString())
    }
</div> 
}
4

2 回答 2

1

Raphaël Althaus 关于您的视图模型和控制器代码是正确的。试试这个:

视图模型:

public class MeWallPostViewModel
{
    public string PostTitle { get; set; }
    public string PostContent { get; set; }
    public DateTime PublishDate { get; set; }

    public MeTagViewModel[] Tags { get; set; }

    public class MeTagViewModel
    {
        public int MeTagId { get; set; }
        public string Name { get; set; }
    }
}

控制器:

public ViewResult Index()
{
    MeWallPostViewModel[] viewModels = null;
    using (var db = new DatselleDB())
    {
        viewModels = db.MeWallPosts
           .Include(p => p.MeWallPostMeTags.Select(t => t.MeTag))           
           .Select(p => new MeWallPostViewModel
           {
               PostTitle = p.PostTitle,
               PostContent = p.PostContent,
               PublishDate = p.PublishDate,
               Tags = p.MeWallPostMeTags.Select(t => 
                   new MeWallPostViewModel.MeTagViewModel
                   {
                       MeTagId = t.MeTagId,
                       Name = t.Name,
                   })
                   .ToArray()
               ),
           })
           .ToArray();
    }
    return View(viewModels);
}

看法:

@model IEnumerable<MeWallPostViewModel>

@foreach (var item in Model)
{
    <div class="postItem clear">
        <h3>@Html.DisplayFor(m => item.PostTitle)</h3>
        <span class="date">@Html.DisplayFor(m => item.PublishDate)</span>
        <p>@Html.DisplayFor(m => item.PostContent)</p> 
        foreach (var tag in item.Tags)
        {
            @Html.DisplayFor(m => tag.Name)
        }
    </div> 
}

另一个想法:

使用AutoMapper清理控制器SelectToArray代码。

回复评论

对于您的第一个问题,请阅读此内容。基本上,除非您以后需要添加或删除项目,否则不要将其转换为列表。在将实体转换为视图模型的情况下,您应该很少需要在从数据库中查询出来后添加或删除项目。

关于你的第二个问题,看我的事后想法。使用 AutoMapper,您的控制器代码最终可能如下所示:

public ViewResult Index()
    {
        // same # of lines as your original GetPosts (not counting this comment)
        MeWallPost[] entities = null;
        using (var db = new DatselleDB())
        {
            entities = db.MeWallPosts
               .Include(p => p.MeWallPostMeTags.Select(t => t.MeTag))
               .ToArray();
        }

        // technically, CreateMap should not be in the controller, but instead
        // bootstrapped once from the composition root (global.asax)
        Mapper.CreateMap<MeTag, MeWallPostViewModel.MeTagViewModel>();
        Mapper.CreateMap<MeWallPost, MeWallPostViewModel>()
            .ForMember(d => d.Tags, o => o.ResolveUsing(s => 
                Mapper.Map<MeWallPostViewModel.MeTagViewModel[]>
                    (s.MeWallPostMeTags.Select(a => a.MeTag))))
        ;

        var viewModels = Mapper.Map<MeWallPostViewModel[]>(entities);
        return View(viewModels);
    }

同样在您的问题中,您将一个实体与视图模型混合在一起:

public class MeWallPostViewModel
{
    private IEnumerable<MeTag> _Tags = new List<MeTag>();
    public IEnumerable<MeTag> Tags
    {
        get { return _Tags; }
        set { _Tags = value; }
    }

每次从实体 DTO 到视图模型时,您应该为原始实体的导航和(在您的情况下)要包含在视图中的集合属性实现单独的视图模型。

于 2012-04-12T17:50:46.550 回答
0

编辑:对不起。

你的代码有点奇怪。

  • 不要将 db 放在您的视图模型中
  • 您的 GetPosts 方法没有任何意义(与类及其属性无关......为什么?)

我至少会做(远非好,但已经更好)

将您的 GetPosts() 方法作为私有方法放在控制器中(这不是最好的方法,但这会更好)。

我希望你的数据库实现 Disposable,所以使用它

然后

public ViewResult Index() {
   return View(GetPosts())
}

你的视图索引应该有@model IEnumerable

然后在你看来

@foreach (var post in Model) {
 bla bla
}

编辑2: 顺便说一句,尝试调试您的查询以查看它是否返回任何内容

于 2012-04-12T16:04:57.737 回答