将查询结果传递给View的最佳做法?

时间:2015-08-28 12:20:27

标签: c# asp.net-mvc asp.net-mvc-5

我是ASP.NET MVC的新手,只是好奇下一个场景的最佳做法是什么。我想将查询结果传递给视图:

public class HomeController : Controller
{
  public ActionResult Index() // show last 3 posts from the database
  {
    DB db = new DB(); // DB is just a tiny wrapper to work with LocalDB sql database
    db.openConnection(ConfigurationManager.ConnectionStrings["PostDBContext"].ConnectionString);      
    db.select(@"select p.id, p.title, p.content, FORMAT(p.created_at, 'yyyy-MM-dd') as created_at, u.firstname,
                                u.lastname, c.name
                       from posts p
                               inner join users u on (u.id = p.created_by)
                               inner join categories c on (c.id = p.category_id)
                       where p.visibility = 'public'
                       order by p.id desc limit 3");

  while( db.read() > 0 ) // reads one row
  {
    ....
  }
  db.closeConnection();
  return View();
}

我已经阅读了几篇关于如何将数据从控制器传递到视图的文章。每篇文章都提到最好的和推荐的方法是将数据从Model传递给View或创建ViewModels。所以使用这种方法意味着我需要创建一个ViewModel和一个Model,如下所示:

public class FullPostViewModel
{
  public List<FullPost> Posts { get; set; }
}

public class FullPost
{
  public int id;
  public string title;
  public string content;
  public string created_at;
  public string author_firstname;
  public string author_lastname;
  public string category;
}

然后在控制器中:

....
FullPostViewModel model = new FullPostViewModel();

while( db.read() > 0 ) // reads one row
{
  model.Posts.Add( new FullPost(){id = Convert.ToInt32(db[0]), title = db[1], ....});
}
...
return View(model);

或者制作三个模型更好:帖子,类别,用户然后FullPost包含这样的内容:

public class FullPost
{
  public Post p;
  public Category c;
  public User u;
}

如果您有更复杂的查询(3,4,...连接),这将意味着为每个表创建新类。当然,为每个表创建一个类是有意义的,因为这就是ORM的全部内容。

我只想知道使用Models / ViewModels是否始终是显示查询结果的最佳实践(我知道ViewBag的简单和小数据)?在Laravel(PHP)中,当涉及到涉及连接的查询时,我经常没有使用模型。它似乎更容易,并不意味着它的确定。

2 个答案:

答案 0 :(得分:2)

我建议您只传递渲染视图所需的数据。由于您可以创建许多视图模型,因此您可以根据需要随意添加属性。

例如:

如果要显示帖子列表:return View(List<LightWeightFullPost>) 如果您想详细展示帖子:return View(FullPost)

对于LightWeightFullPost,您只需发送帖子名称和作者即可。这样可以使您发送的数据尽可能小,因为您不希望在列表视图中显示每个细节。

只有在您确实需要时,才建议在ViewModel中传递复杂对象。 例如:在响应FullPost ViewModel时,您真的需要完整的Category对象吗?或者是CategoryId足够吗?

答案 1 :(得分:1)

1)将您的应用程序分层。不要在控制器中放置SQL查询,在服务层中执行此操作。

2)您可以将业务对象返回给Views,但返回ViewModel会更好,更灵活。这样你就不需要发送任何你不需要的额外字段,你可以将多个类混合成一个。此外,如果需要,您可以在Controller中处理格式化。

3)如果您的View在所有地方都有逻辑,请再想一想,您可能做错了。尝试使用简单的视图,只需处理HTML并显示属性。

根据一条评论,我在下面添加了额外信息: 有时您需要格式化十进制或DateTime属性或将多个属性合并为一个属性。在Controller中比在View中更好。我们假设您需要显示金额,包括货币和小数。您可以在视图或控制器中执行此操作。如果您在视图中执行此操作,则视图中将包含更多逻辑。然后,如果您对同一页面有不同的视图(例如该页面的移动视图),则需要执行两次或为此创建局部视图。如果你在控制器中这样做,你可以做一次,你可以轻松测试它。