在ASP.NET MVC中的ViewModel类上使用Bind属性

Nic*_*ick 16 c# asp.net-mvc

为什么开发人员可能Bind在ASP.NET MVC项目中的ViewModel对象上使用该属性,这会对应用程序产生不利影响吗?

[Bind(Include = "Id,Name")]
[MetadataType(typeof (MyViewModelValidation))]
public class MyViewModel
{
    public string CustomerProductUserName { get; set; }

    [Display(Name = "Name")]
    public string Name { get; set; }

}

public class MyViewModelValidation
{
    [HiddenInput(DisplayValue = false)]
    public int Id { get; set; }

    [Required]
    public string Name{ get; set; }
}
Run Code Online (Sandbox Code Playgroud)

ata*_*ati 19

首先,您不需要MetadataType为ViewModel 创建类.您可以直接在ViewModel中使用数据注释属性.MetadataType类用于由EF或其他ORM自动生成的模型,因此您可以使用数据注释属性而无需触及自动生成的代码.

Bind属性没有被使用,也可以-除非你想使用IncludeExclude绑定属性的特性,包括或在您的模型或分别结合,排除特性.

例如,在您的问题的代码中,从View中提交模型时,只会绑定IdName属性.即使您在View for中有输入CustomerProductUserName,当您提交表单时,该属性也将始终为null.这在您不希望将自动生成的ID字段包含在绑定中的情况下非常有用.

从绑定中排除的属性也会从验证中排除,因为验证是作为模型绑定的一部分完成的.此外,Bind出于安全原因,您可以使用该属性; 例如,当您想要确保模型中的属性被发布到控制器时.


小智 15

使用bind属性的目的是防止攻击者在发布请求时分配属性值或控制要绑定的属性.

让我们假设,你有一个叫做的类Member和一个保存成员的create方法.但是您不希望用户发送MemberType属性值.

Class Member  
{  
    public int MemberId { get; set; }  
    public string FirstName { get; set; }  
    public string LastName { get; set; }  
    public string MemberType { get; set; }  
}  

[HttpPost]  
Public ActionResult Create(Member member)  
{  
    Save(member);  
}
Run Code Online (Sandbox Code Playgroud)

我们现在说,您只提供常规成员类型,这是默认值.您可能认为可以通过不允许输​​入MemberTypeProperty 来阻止用户为MemberType属性发送值.但是当用户发布成员对象时,攻击者可能会拦截请求并在请求中发送MemberType值 MemberId=1&FirstName=Chandra&LastName=Malla&MemberType=Premium,并将该成员保存为Premium成员.为了防止这种情况,您可以Member使用Bind属性修饰类.

[Bind(Include="MemberId,FirstName,LastName")]  
Class Member  
{
    ...
Run Code Online (Sandbox Code Playgroud)

要么

[Bind(Exclude="MemberType")]  
Class Member  
{  
    ...
Run Code Online (Sandbox Code Playgroud)

现在,如果Member发布了对象,则不会发布MemberType属性值.

如果您使用的是ViewModel,则可能不一定必须使用bind属性,因为您可以在ViewModel中省略MemberType属性.

Class Member  
{  
    public int MemberId { get; set; }  
    public string FirstName { get; set; }  
    public string LastName { get; set; }  
    public string MemberType { get; set; } 
}  

Class MemberViewModel  
{       
    public int MemberId { get; set; }   
    public string FirstName { get; set; }  
    public string LastName { get; set; }  
}  

[HttpPost]  
Public ActionResult Create(MemberViewModel memberviewmodel)  
{  
    Save(memberviewmodel);  
}
Run Code Online (Sandbox Code Playgroud)

如果您没有很好地设计模型和/或ViewModel,并且不使用bind属性来避免发布您不想要的属性,那可能会产生不利影响.


juF*_*uFo 5

此外,如果您想在从模型中重命名属性时防止出现重构问题,您可以执行以下操作:

public async Task<ActionResult> Create([Bind(Include = nameof(Foo.Bar1)+","+nameof(Foo.Bar2)+","+nameof(Foo.Bar3))] Foo fooObj)
Run Code Online (Sandbox Code Playgroud)

如果您现在重命名“Bar1”,则您的包含绑定仍然有效。