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

发布于 2024-08-29 05:36:51 字数 103 浏览 6 评论 0原文

假设我有一个对象,它从 HttpPost 获取一些数据,从数据库获取一些数据。我想我想允许 ModelBinder 访问数据库/存储库以获取帖子中丢失的数据。实际上,这是一个好主意还是坏主意?

Say I have an object that gets some data from HttpPost and some from the database. I think I want to allow the ModelBinder to go to the database/repository for the that data missing from the post. In practice, is this a good or bad idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

简单 2024-09-05 05:36:51

鉴于我对此类事情的思考自 2010 年初以来已经发生变化,我决定编辑我原来的答案。

在我原来的答案中,我基本上表达了这一点,虽然我的直觉告诉我你不应该这样做,但我很不舒服地说我们不应该在无法阐明原因的情况下。

现在,我建议不要这样做,因为模型绑定器的职责是将用户请求转换为请求模型,并且检索可从请求派生的数据之外的数据超出了此责任范围。

I've decided to edit my original answer given my thinking on these types of things has evolved since early 2010.

In my original answer, I basically expressed that, while my instincts told me you shouldn't do this, I was uncomfortable saying we shouldn't without being able to articulate why.

Now, I'd recommend against this on the grounds that the responsibility of a Model Binder is to translate a user request into a Request Model and that retrieving data outside of what can be derived from the request goes beyond this scope of responsibility.

南烟 2024-09-05 05:36:51

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

I would say a bad idea. The idea of the model binder is that it takes the parameters from the request and creates your model from those. If your model binder, behind the scenes, fills in some of the details from the database this breaks the paradigm. I'd much rather expose the database call in my controller by explicitly fetching the required extra data from the database directly. Note that this could be refactored into a method if used frequently.

鹿港巷口少年归 2024-09-05 05:36:51

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

唯一反对的论点非常迂腐,相当于哲学争论。恕我直言,您可以将“填充丢失的已发布数据”代码作为基本控制器中的方法与 ActionFilter 中的方法与 ModelBinder 中的方法放入 MVC 应用程序中。这完全取决于谁承担什么责任。对我来说,模型绑定器可以做的不仅仅是简单地从发布的值连接一些属性。

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

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

        return View( new MODEL() );
    }

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

I think this is perfectly fine and use this technique all the time.

The only arguments against are very pedantic and amount to arguing over philosophy. IMHO you can put "fill in missing posted data" code into you MVC app as a method in your base controller vs. method in you ActionFilter vs method in you ModelBinder. It all depends on who get what responsibility. To me the model binder can do a lot more than simply wire up some properties from posted values.

The reason I love doing database calls in my modelbinder is because it helps clean up your action methods.

    //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() );
    }
慕巷 2024-09-05 05:36:51

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

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

更进一步,假设您想在数据库中记录用户未发布的信息,或者在获取丢失的数据并向管理员发送电子邮件时捕获异常。您必须以这种方式将它们放入模型绑定器中,并且随着模型绑定器变得越来越偏离其原始用途,它会变得越来越难看。

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

It violates the way MVC is supposed to work. ModelBinder is for binging Models from the data that comes from the view. Populating missing info from the database is something that is supposed to be handled by the controller. Ideally, it would have same data layer/repository class that it uses to do this.

The reason it should be in the controller is because this code is business logic. The business rules dictate that some data may be missing and thus it must be handled by the brains of the operation, the controller.

Take it a step further, say you want to log in the DB what info the user isn't posting, or catch an exception when getting the missing data and email admins about it. You have to put these in your model binder this way and it gets more and more ugly with the ModelBinder becoming more and more warped from its original purpose.

Basically you want everything but the controller to be as dumb and as specialized as possible, only knowing out how to carry out its specific area of expertise which is purely to assist the controller.

千寻… 2024-09-05 05:36:51

我会说,不。

原因如下:它将创建对数据库的依赖关系,以测试控制器操作,而这种依赖关系不容易抽象出来。

I would say, no.

Here's why: It would create a dependency on your database for testing your controller actions that would not be easy to abstract out.

滴情不沾 2024-09-05 05:36:51

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

1- 数据库访问应该通过存储库接口进行抽象。存储库接口是域模型的一部分,其实现是基础设施/数据访问层的一部分。所以对数据库没有依赖性。

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

此外,在某些情况下,您“最好”从模型绑定器填充模型中缺失的数据。考虑视图上有一个下拉列表的场景。第一次加载视图时,会填充下拉列表。用户提交表单但验证失败。因此,您需要再次退回表格。在此阶段,您必须重新填充下拉列表模型中的列表。在控制器中执行此操作看起来很丑陋:

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

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

I would say it is ok. The argument that creates dependency to database is a false argument for 2 reasons:

1- Database access should be abstracted via repository interfaces. Repository interfaces are part of the domain model and their implementation is part of the infrastructure/data access layer. So there is no dependency to the database.

2- Model Binders and Controllers are both part of presentation layer implemented using ASP.NET MVC Framework. If Controllers are allowed to access database using repository interfaces, how come Model Binders are not allowed?

Also, there are situations that you'd "better" fill the missing data in your model from Model Binders. Consider the scenario where you have a drop-down list on your view. The first time the view is loaded, the drop-down list is populated. The user submits the form but the validation fails. So you'll need to return the form again. At this stage, you'll have to re-populate the list in the Model for the drop-down list. Doing this in Controller looks ugly:

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

I believe the initialization of Categories here is ugly and like a code smell. What if you had a few properties that needed to be filled out from database? What if you had more than 1 action that had DocumentViewModel as an argument? You'd have to repeat this ugly step over and over. A better approach is to fill all the properties of the model using the Model Binder and pass it to the Controller. So the object that is passed to the controller is in a "consistent" state.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文