MVC如何保持模型瘦

时间:2009-09-23 18:41:38

标签: model-view-controller model controller

看了这个video后,我想知道我是否使用了我的控制器。控制器到底应该包含什么?

对于我的博客,我有一个帖子控制器,它有方法: 创建 节目 名单 loadPost 喜欢 不喜欢

而我的帖子模型只有一些访问规则,验证规则和关系信息。网上有MVC应用程序的例子吗?

3 个答案:

答案 0 :(得分:8)

我强烈推荐阅读 http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/04/24/how-we-do-mvc.aspx

这是我不完整的控制器不应该做的列表:

  • 将帖子数据绑定到视图模型 - 不,模型绑定器应该这样做
  • 从存储库中获取实体 - 我会说不,模型绑定器或操作过滤器应该
  • 计算一些东西 - 不,查看模型或实体
  • 授权 - 也许,但最好转移到属性/过滤器
  • 验证 - 仅当它从实体/域(即业务规则)返回时,应自动处理视图模型(表示)验证(绑定器等)

应该这样做:

  • 获取绑定,验证的视图模型作为输入
  • 调用域图层,从视图模型传递数据
  • 处理域图层错误
  • 根据视图模型/域结果路由到适当的操作/视图

为:

public ActionResult PlaceOrder(Guid orderid)
{
  if (HttpContext.Session["user"] == null)
    return Redirect("Login");
  if (!ValidOrderId(orderid)) return Redirect();
  var order = cart.Get(orderid);
  if (order == null) { ViewData["orderid"] = orderid; return View("Select"); }
  order.Status = OrderStatus.Placed;
  foreach (var item in order.Items)
    item.Update();
  var cart = Cart.GetCurrent();
  cart.Save(order);
  return Redirect("Show", "Orders", new { orderid = orderid });
}

[Authorize]
[ModelStateToTempData]
// OrderViewModel.Id/OrderViewModel.Instance - validates id, 
// gets it from repository, set Instance or ModelState error
public ActionResult PlaceOrder(OrderViewModel<Order> order)
{
  if (!ModelState.IsValid)
     return View("Select", order);
  var order = order.InstanceFromDatabase;
  _injectedCart.SetOrderPlaced(order);
  return RedirectToAction<OrdersController>(c => c.Show(order));
}

顺便说一句,我很少看到好的MVC示例,包括NerdDinner。它们都处理动作中的业务逻辑,没有视图模型等等。这通常适用于他们的意图 - MVC功能演示 - 但它不应被视为好的设计示例。一个或多或少好的例子是CodeCampServer,以及伴奏书ASP.NET MVC In Action。但并非没有缺点(例如贫血领域模型)。

但是,如果不尝试遵循域驱动设计,而是拥有简单的数据驱动要求,那么事情就更容易了。

答案 1 :(得分:1)

我尝试使用胖视图模型和瘦控制器,控制器为我的业务对象提供工作。

NerdDinner是一个很好的示例应用程序,但StackOverflow是我最喜欢的MVC网站示例。

善,

答案 2 :(得分:1)

控制器应包含足够的逻辑来解释用户在将处理传递到服务层之前所说的内容。 因此,如果用户说“将此帖标记为我喜欢的帖子”,则通过单击“赞”按钮,控制器会确保用户已获得授权,然后让服务层句柄实际执行标记帖子的工作等。 如果用户说“创建新博客条目”,则控制器将收集帖子,标签,时间戳和其他相关信息,并对数据进行最小化验证。然后它将处理交给服务层。如果服务层发现问题,那么它应抛出一个异常,然后您可以在控制器中处理它。