【问题标题】:Need guide line for MVC action method with Bind attribute需要具有 Bind 属性的 MVC 操作方法的指南
【发布时间】:2013-10-21 08:59:48
【问题描述】:

我正在浏览一个动作方法代码,我看到那里使用了一个属性,但我真的不明白它的用途。这是代码

public ActionResult User([Bind(Include = "Username,FullName,Email")]User user)
{
   if (!ModelState.IsValid()) return View(user);

   try
   {
     user.save()
     // return the view again or redirect the user to another page
   }
   catch(Exception e)
   {
     ViewData["Message"] = e.Message;
     return View(user)
   }
}

([Bind(Include = "Username,FullName,Email")]User user)

我只是不明白上面那一行 Bind include etc

所以请帮助我理解当人们在 mvc 中编写这种代码时使用的这种属性。如果有人通过示例小代码让我理解他们将在哪里使用Bind attribute,那将是非常好的帮助。

更新: 假设我有表单,用户只能输入名字、姓氏和性别,那么我的操作方法看起来像

public ActionResult Edit(string FirstName,string LastName,string Gender)
{
    // ...
}

我认为这会起作用。那为什么我应该使用绑定属性,因为我上面的操作方法可以正常工作。

【问题讨论】:

  • 根据您的编辑:如果您按照建议的方式“分块”数据,您将失去 MVC(以及堆栈中的其他技术)必须提供的许多东西。另外,如果您的Person 课程发生变化怎么办?如果您有其他操作对此类型执行操作怎么办?那么单元测试呢?映射到其他层(服务、DAL 等)?

标签: c# asp.net-mvc asp.net-mvc-3


【解决方案1】:

Bind 属性可让您“微调”特定参数类型的模型绑定过程,而无需注册特定于该类型的自定义 ModelBinder

例如,假设您的 Action 需要一个 Person 参数,定义如下:

public class Person
{
    public Person(string firstName, string lastName, Gender gender)
    {
        this.FirstName = firstName;
        this.LastName = lastName;

        if (gender == Gender.Male)
            this.FullName = "Mr. " + this.FirstName + " " + this.LastName;
        else
            this.FullName = "Mrs. " + this.FirstName + " " + this.LastName;
    }

    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Gender Gender { get; set; }

    // 'FullName' is a computed column:
    public string FullName { get; set; }
}

还有行动:

public ActionResult Edit(Person person)
{
    ...
}

现在,如果有人发布以下 JSON:

{
    "FirstName":"John",
    "LastName":"Smith",
    "Gender":"Male",
    "FullName":"Mrs. John Smith"
}

您的 Action 现在将有一个 person 和错误的 FullName('Mrs' 而不是 'Mr')。

为避免此类行为,您可以使用Bind 属性并从绑定过程中明确排除FullName 属性(“黑名单”):

public ActionResult Edit([Bind(Exclude="FullName")] Person person)
{
    ...
}

或者,您可以使用Include 忽略('Black-list')所有属性,只包括('White-list')指定的属性:

public ActionResult Edit([Bind(Include="FirstName,LastName,Gender")] Person person)
{
    ...
}

更多关于MSDN的信息。

【讨论】:

    【解决方案2】:

    执行此操作时,MVC 模型绑定器将使用请求参数来填充user 参数的属性,您可能已经知道了。但是,Bind 属性告诉模型绑定器填充具有指定名称的属性。

    所以在这种情况下,只会填充 UsernameFullNameEmail 属性。其他所有将被忽略。

    更多详情请看这里:http://ittecture.wordpress.com/2009/05/01/tip-of-the-day-199-asp-net-mvc-defining-model-binding-explicitly/

    【讨论】:

      【解决方案3】:

      Bind 属性是在创建场景中防止过度发布的一种方法。例如,假设 Student 实体包含您不希望此网页设置的 Secret 属性。

      public class Student
      {
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }
        public string Secret { get; set; }
      
        public virtual ICollection<Enrollment> Enrollments { get; set; }
      }
      

      即使网页上没有 Secret 字段,黑客也可以使用 fiddler 等工具或编写一些 JavaScript 来发布 Secret 表单值。如果没有 Bind 属性限制模型绑定器在创建 Student 实例时使用的字段,模型绑定器将获取该 Secret 表单值并使用它来创建 Student 实体实例。然后,黑客为 Secret 表单字段指定的任何值都将在您的数据库中更新。下图显示了将 Secret 字段(值为“OverPost”)添加到已发布表单值的提琴手工具。 然后,“OverPost”值将成功添加到插入行的 Secret 属性中,尽管您从未打算让网页能够设置该属性。

      将 Include 参数与 Bind 属性一起使用以将字段列入白名单是一种安全最佳做法。也可以使用 Exclude 参数将要排除的字段列入黑名单。 Include 更安全的原因是当您向实体添加新属性时,新字段不会自动受到 Exclude 列表的保护。

      【讨论】:

        猜你喜欢
        • 2012-08-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多