【问题标题】:How to avoid placing domain logic in controller?如何避免将域逻辑放在控制器中?
【发布时间】:2010-09-20 04:21:13
【问题描述】:

关于 PRO ASP.NET MVC 书:

当然可以放域名 逻辑到控制器中,即使 你不应该,只是因为看起来 在压力大的时候权宜之计。

只是一个人为的例子,如果应用程序不允许负订单,那么在哪里将数量更改为 1?如果我们遵循域逻辑不应该放在控制器中的原则,这当然是不可取的:

[AcceptVerbs(HttpVerbs.Post)]        
public ActionResult PlaceOrder(Order order)
{
 if (ModelState.IsValid)
 {
  order.Submit();
  return View("Thanks", order);
 }
 else
 {
    if (order.Quantity <= 0)
    {
        ModelState.Remove("Quantity");
        order.Quantity = 1;  
    }
    return View(order);
 }
}

所以下面的代码是符合 MVC 原则的正确代码,即它遵循关注点分离,如果它是域逻辑,你不应该在控制器中看到它的代码。所以这就是我尝试将域逻辑放在模型中的方式:

public class Order : IDataErrorInfo
{
 public int OrderId { set; get; }
 public int ProductId { set; get; }
 public int Quantity { set; get; }

 public string Error { get { return null; } }

 public string this[string propName]
 {
  get
  {
   if (propName == "Quantity" && Quantity <= 0)
   {
    Quantity = 1;
    return "0 or negative quantity not allowed, changed it to 1";
   }
   else
    return null;

  }
 }
}

控制器(无域逻辑):

[AcceptVerbs(HttpVerbs.Post)]        
public ActionResult PlaceOrder(Order order)
{
 if (ModelState.IsValid)
 {
  order.Submit();
  return View("Thanks", order);
 }
 else
 {
  // Response.Write(order.Quantity.ToString()); // this was changed in Model
  return View(order); // but the View didn't reflect that fact
 }
}

这种方法的唯一问题是,Model(Order) 不能影响 ModelState,因此程序总是显示用户最后输入的任何内容。

最好的方法是什么,这样我仍然可以避免在控制器中放置域逻辑并且视图仍然能够反映模型属性的值?

【问题讨论】:

    标签: c# asp.net-mvc


    【解决方案1】:

    验证不是控制器任务。您可以将所有需要的逻辑放在不同的模块中,然后在那里传播请求。

    【讨论】:

      【解决方案2】:

      啊,但是业务层可以影响模型状态。查看this tutorial 使用服务层进行验证。它也是对存储库和控制反转的一个很好的介绍。

      一般的方法是为模型状态创建一个包装器,该包装器实现一个简单的接口,用于向模型状态添加错误。您的业​​务层对接口起作用 - 因此它与您的模型状态没有联系。您的单元测试可以实现一个假包装器,该包装器也实现了相同的接口。

      看起来您的具体示例正在将用户的无效输入更改为有效输入。我的建议是简单地留下无效的输入,并在控制器返回视图时使用 AddModelError 来反映这一点。

      【讨论】:

      • 除了具体的例子,有没有办法让模型与模型状态同步?理想情况下(正如 MVC 鼓励的原则)ModelState 的更新不应该在 Controller 上完成
      猜你喜欢
      • 2015-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2016-03-18
      • 1970-01-01
      • 2020-08-12
      • 1970-01-01
      相关资源
      最近更新 更多