【问题标题】:Adding Function To Controllers Before Saving保存前向控制器添加功能
【发布时间】:2014-01-26 19:52:49
【问题描述】:

我正在尝试找出一种好的(“最好”,如果可能的话)方法来构建一个解决方案,在该解决方案中,我可以在使用 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. 我考虑过在实用程序类中创建一个静态函数,它将我的模型(在本例中为保修模型)作为参数——但是我不知道接收函数应该接受泛型类型还是对象“对象”类型的类型——两者都需要一些反射代码,以便我知道传递了什么模型。我可能会有一个大的“if”块来查看类型(如果是角色,则执行此操作;如果是用户,则执行此操作;等等)。我的控制器中的调用可能看起来像这样:

    Utility.PreSaveChanges(warrantymodel);
    

如果您认为这是最好的方法,PreSaveChanges 应该有一个 object 类型的参数还是应该接受一个泛型类型?

  1. 我还认为我可以将预保存功能放在模型本身中。如上所述,我喜欢在模型中包含预保存功能代码的想法,但我只是不知道这是否是个好主意。该代码如下所示:

    warrantymodel.PreSaveChanges();
    

如果您认为这是最好的方法,您能否确认在模型中包含函数是可以的?这会打破某种 MVC 原则吗?

我只触及了依赖注入的皮毛——所以我不知道这是否会有所帮助。如果可以的话,我很想看一个简短的例子(我已经阅读了足够多的关于 DI 的内容,无需太多解释就可以理解它)。

【问题讨论】:

  • 您的问题源于您的数据对象、业务对象和 UI 对象都是同一事物。您需要使用视图模型。
  • 是的,这只是 MVC 脚手架提供的控制器逻辑中的一个简单示例。我理解并同意应该涉及更多的模型。我感谢您的建设性批评,但这个问题的重点更多地与添加预保存逻辑的位置有关,模型架构除外。

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


【解决方案1】:

你的模型类中不仅可以有函数,如果你在那个实体上做任何工作,也应该有。将模型的行为和逻辑封装在它所属的模型类中。永远不在控制器中!想想 FAT 模型,SKINNY 控制器。

其次,如果您想在所有模型上实现 PreSaveChanges 函数,我可能会创建一个类似 IPreSaveFunctionality 的接口,其中包含一个 PreSaveChanges 方法存根,并让每个模型实现您想要的这个接口可以PreSaveChanges

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

【讨论】:

  • 很高兴听到 - 在我继续使用 MVC 时,我会牢记胖/瘦的口头禅!
【解决方案2】:

有几个选项:

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

2) 另一种选择,您可以让所有模型都继承自“香草”模型,当您收到“特殊”模型时,只需将该模型向下转换为香草模型并将其发送到实用程序方法进行处理。

【讨论】:

  • 查看我对 Ant P 的评论——我真的更关心在哪里/如何扩展控制器逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-04-27
  • 1970-01-01
  • 2014-11-07
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 2019-01-09
相关资源
最近更新 更多