可以从自定义模型绑定器中访问数据库吗?

时间:2010-04-17 13:00:57

标签: asp.net-mvc modelbinders

假设我有一个从HttpPost获取一些数据的对象和一些来自数据库的数据。我想我想允许ModelBinder转到数据库/存储库以获取帖子中缺少的数据。在实践中,这是一个好主意还是坏主意?

6 个答案:

答案 0 :(得分:6)

我决定编辑我的原始答案,因为我对这些类型的事物的思考自2010年初以来一直在发展。

在我原来的回答中,我基本上表示,虽然我的直觉告诉我你不应该这样做,但我不能说我们不能不明白为什么这样做。

现在,我建议不要这样做,理由是Model Binder的责任是将用户请求转换为请求模型,并且检索可以从请求中获得的数据之外的数据超出了这个责任范围

答案 1 :(得分:4)

我会说一个坏主意。模型绑定器的想法是它从请求中获取参数并从中创建模型。如果您的模型绑定器在幕后填充了数据库中的一些细节,那么这就打破了范式。我宁愿通过直接从数据库中显式获取所需的额外数据来在我的控制器中公开数据库调用。请注意,如果频繁使用,可以将其重构为方法。

答案 2 :(得分:2)

我认为这非常好,并且一直使用这种技术。

反对的唯一论点非常迂腐,相当于对哲学的争论。恕我直言,您可以将“填写缺失的发布数据”代码放入MVC应用程序作为基本控制器中的方法与您在ModelBinder中的ActionFilter vs方法中的方法。这一切都取决于谁得到了什么责任。对我来说,模型绑定器可以做很多事情,而不仅仅是从发布的值中连接一些属性。

我喜欢在我的模型绑定器中进行数据库调用的原因是因为它有助于清理您的操作方法。

    //logic not in modelbinder
    public ActionResult Edit( KittyCat cat )
    {
        DoSomeOrthagonalDatabaseCall( cat );

        return View( new MODEL() );
    }

VS

    //logic in model binder
    public ActionResult Add( KittyCat cat )
    {
        return View( new MODEL() );
    }

答案 3 :(得分:2)

它违反了MVC的工作方式。 ModelBinder用于根据视图中的数据绑定模型。从数据库中填充缺少的信息应该由控制器处理。理想情况下,它将使用相同的数据层/存储库类来执行此操作。

它应该在控制器中的原因是因为此代码是业务逻辑。业务规则规定某些数据可能会丢失,因此必须由操作的大脑即控制器处理。

更进一步,假设您想要在数据库中登录用户未发布的信息,或在获取缺失数据时收到异常,并向管理员发送有关它的信息。你必须以这种方式将它们放入你的模型绑定器中,并且随着ModelBinder变得越来越歪曲,它会变得越来越难看。

基本上你希望除了控制器以外的所有东西都尽可能愚蠢和专业,只知道如何执行其专业领域,这纯粹是为了协助控制器。

答案 4 :(得分:1)

我会说,不。

原因如下:它会在您的数据库上创建一个依赖项,用于测试不容易抽象出来的控制器操作。

答案 5 :(得分:1)

我会说没关系。创建与数据库的依赖关系的参数是一个错误的参数,原因有两个:

1-应通过存储库接口抽象数据库访问。存储库接口是域模型的一部分,它们的实现是基础架构/数据访问层的一部分。所以不依赖于数据库。

2-模型绑定器和控制器都是使用ASP.NET MVC Framework实现的表示层的一部分。如果允许控制器使用存储库接口访问数据库,那么为什么不允许使用模型绑定器?

此外,在某些情况下,您可以“更好地”从模型库中填充模型中的缺失数据。考虑一下您的视图上有下拉列表的情况。第一次加载视图时,将填充下拉列表。用户提交表单但验证失败。所以你需要再次返回表格。在此阶段,您必须重新填充模型中的下拉列表中的列表。在Controller中执行此操作看起来很难看:

public ActionResult Save(DocumentViewModel viewModel)
{
     if (!ModelState.IsValid)
     {
         viewModel.Categories = _repository.GetAll();
         return View(viewModel);
     }
}

我相信这里的类别初始化是丑陋的,就像代码味道一样。如果您有一些需要从数据库填写的属性怎么办?如果您有多个具有DocumentViewModel作为参数的操作,该怎么办?你必须一遍又一遍地重复这个丑陋的步骤。更好的方法是使用Model Binder填充模型的所有属性并将其传递给Controller。因此传递给控制器​​的对象处于“一致”状态。