保存前向控制器添加功能

时间:2014-01-26 19:52:49

标签: c# asp.net-mvc entity-framework controller

我试图找出一个好的(“最好的”,如果可能的话)构建解决方案的方法,在使用EF6将更改提交回数据库之前,我可以在控制器中对MVC模型进行一些工作。

所以这是一个例子 - 我在我的一个控制器类中有这个代码:

    [HttpPost]
    [ValidateAntiForgeryToken]      
    public ActionResult Edit(Role role)
    {
        if (ModelState.IsValid)
        {
            db.Entry(role).State = EntityState.Modified;
    //***********---> HERE IS WHERE I WOULD PLACE THE PRE-SAVECHANGES CALL
            db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(role);
    }

如上所述,我想在db.SaveChanges()之前调用“pre-savechanges”函数。关键是我想为我的所有控制器执行此操作,并且我希望在所有控制器中调用此函数的方式相同,以便此预保存实现是一致的(换句话说,函数名应该相同,它应该将模型作为参数 - 我试图避免以任何方式将函数的名称绑定到模型名称。例如,该函数可以被称为PreSaveChanges,它需要访问即将持久化的模型(角色,在这种情况下,在上面的代码中描述)。

我知道有很多方法可以实现这一点,但我想到的一种方法是只为每个模型添加一个函数 - 但我没有看到模型中的函数示例,而且我没有足够的经验来理解这种方法的后果(如可测试性)。我还考虑过某种控制反转/依赖注入解决方案,因为这似乎是一种流行的选择。无论采用何种方法,我都不希望要求pre-savechanges功能需要实际存在。换句话说,某些控制器将具有在持久化之前需要预处理的模型,而其他控制器则不会。我仍然希望我的所有控制器都尝试调用pre-savechanges函数,但如果它尚未定义或不存在那么那很好 - 那么dbSaveChanges()行应该在下一步执行。

所以,快速浏览一些选项:

  1. 我考虑在实用程序类中创建一个静态函数,它将我的模型(在本例中为powersymodel)作为参数 - 但后来我不知道接收函数是否应该接受泛型类型或“对象”类型的对象 - 两者都需要一些反射代码,以便我知道已经传递了什么模型。我可能会有一个大的'if'块来查看类型(如果是角色,那么就这样做;如果是用户,那么就这样做;等等)。我的控制器中的调用可能看起来像这样:

    Utility.PreSaveChanges(warrantymodel);
    
  2. 如果您认为这是最佳方法,PreSaveChanges是否应该具有object类型的参数,还是应该接受泛型类型?

    1. 我还以为我可以将预保存功能放在模型中。我喜欢在模型中包含预保存功能代码的想法,如上所述,但我不知道这是不是一个好主意。该代码看起来像这样:

      warrantymodel.PreSaveChanges();
      
    2. 如果您认为这是最好的方法,您能否确认在模型中有功能?这会破坏某种MVC原则吗?

      我只涉及依赖注入的表面 - 所以我不知道这是否有帮助。如果愿意的话,我很乐意看到一个简短的例子(我已经阅读了足够的关于DI的内容,我会理解它而不需要太多解释)。

2 个答案:

答案 0 :(得分:0)

有几个选择:

1)正如Ant P建议的那样,制作一个与其他模型不同的“香草”模型,这将是您提交动作时要绑定的模型。然后,创建一个只接受这种类型的模型并使用它的实用程序方法会很容易。

2)另一种选择,你可以让你的所有模型继承自'vanilla'模型,当你收到'特殊'模型时,只需将该模型转发给vanilla模型并将其发送到实用程序方法进行处理。

答案 1 :(得分:0)

不仅模型类中可以有函数,如果您正在对该实体进行任何操作,也应该有。保持模型的行为和逻辑封装在模型类所属的模型中。不在控制器中!想想FAT模型,SKINNY控制器。

其次,如果您想在所有模型上实现PreSaveChanges函数,我可能会创建一个类似IPreSaveFunctionality的接口,其中包含PreSaveChanges方法存根,并且每个模型都有您希望能够PreSaveChanges的此界面。

但是如果对于你传递的任何模型,逻辑将是相同的,那么我将创建一个BaseModel类并在该类中创建一个虚拟方法,并使所有其他模型派生自{{1如果一些模型对此函数有不同的实现,那么您总是可以覆盖该模型类中该单个模型的BaseModel实现。