在mvc中使用控制器中的模型类是不好的做法吗?

时间:2010-10-12 20:53:05

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

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

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

4 个答案:

答案 0 :(得分:4)

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

例如,考虑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; }
  }

您的用户个人资料页面允许用户编辑他们的FirstName,LastName和EmailAddress。

不道德的用户只需修改表单即可将“IsAdmin”与其他值一起发布。因为您的Action期望输入UserProfile,所以IsAdmin值也将被映射,并最终保持不变。

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

我认为直接将实体模型绑定到[HttpGet]方法没有错。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

是的,通过练习。你应该尽可能地将控制器保持为瘦,并将每个问题分开。

答案 3 :(得分:0)

您仍然可以使用特定于视图的模型来处理过帐问题,但是您可以使用更新的 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)
{
    // ...
}

您也可以将它放在实体模型的类名之上,如下所示:

[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; }
  }

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