【问题标题】:Is it a bad practice using model classes in controller in mvc?在 mvc 的控制器中使用模型类是一种不好的做法吗?
【发布时间】:2011-04-24 13:16:32
【问题描述】:

我想与在 asp.net mvc 中使用 ORM 或数据库表时的最佳实践进行比较。我的主要问题之一是我是否应该直接在控制器中实例化 模型类..不查询数据库而只使用模型类来存储值。

例如如果我使用实体框架作为模型......那么使用实体类对象在控制器中是一种不好的做法。有时直接使用控制器中生成的数据库类而不是创建 ViewModel 甚至 ViewData 更容易。我们有一个数据访问层和一个业务层,其中应用了所有查询和业务逻辑,但虽然更容易我不喜欢在控制器中访问模型的想法,但这真的是一个不好的做法 ?

【问题讨论】:

    标签: entity-framework asp.net-mvc-2 viewmodel


    【解决方案1】:

    是的,这是一种不好的做法,因为“过度发布”的问题。

    例如,考虑 UserProfile 的实体模型:

      public class UserProfile
      {
        public string UserName { get; set; }
        public bool IsAdmin { get; set; }
        public string EmailAddress { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
      }
    

    您的用户个人资料页面允许用户编辑他们的名字、姓氏和电子邮件地址。

    不道德的用户可以简单地修改表单以发布“IsAdmin”以及其他值。因为您的 Action 需要 UserProfile 的输入,所以 IsAdmin 值也将被映射,并最终持久化。

    这里是an excellent writeup about the perils of under and overposting

    不过,我认为将实体模型直接绑定到您的 [HttpGet] 方法没有任何问题。

    【讨论】:

    • 所以我应该避免在Posts 上使用它以考虑安全性,但如果我在gets 上使用它就可以了。应该没有问题吧?
    • 是的,没错。我总是为这类事情制作一个快速的 ViewModel,但是如果你想将你的 View 直接绑定到一个实体模型并且它是只读的,我看不到任何风险。
    【解决方案2】:

    是的,通过练习。您应该使控制器尽可能瘦,并将每个关注点分开。

    【讨论】:

      【解决方案3】:

      实际上,这取决于,也许您只需要在 UI 中准确地显示您的模型。然后我认为包装它没有任何意义。但大多数情况下,即使您认为在将模型显示在视图中之前不需要更改模型中的任何内容,您将来也可能需要这样做。因此,更好的方法是将您的确切模型和未来视图数据分开。如果您需要更改某些内容(例如更改数据库结构但视图将保持不变),它会为您提供更大的灵活性

      【讨论】:

        【解决方案4】:

        您仍然可以使用视图特定模型来处理发布问题,但是您可以使用更新的 Bind 属性来实现相同的目的,如 this blog post

        以 Peter J 的实体模型为例。在编辑方法上,您可以简单地这样做:

        [HttpPost]
        public ViewResult Edit([Bind(Include = "UserName, EmailAddress, FirstName, LastName")] User user)
        {
            // ...
        }
        

        并且简单地省略 IsAdmin 项目以防止它在帖子中被使用。

        此外,如博客文章中所述,您可以采用“黑名单”方法并告诉您的控制器操作要排除哪些字段:

        [HttpPost]
        public ViewResult Edit([Bind(Exclude= "IsAdmin")] User user)
        {
            // ...
        }
        

        你也可以把它放在Entity模型的类名之上,像这样:

        [Bind(Exclude="IsAdmin")]
        public class UserProfile
          {
            public string UserName { get; set; }
            public bool IsAdmin { get; set; }
            public string EmailAddress { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
          }
        

        当您只需要从实体模型中排除或包含几个字段时,此方法可能更适合。

        【讨论】:

          猜你喜欢
          • 2015-10-01
          • 2011-11-15
          • 2015-12-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多