C# 在 ASP.NET MVC 中的 ViewModel 类上使用 Bind 属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18276348/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using the Bind attribute on a ViewModel class in ASP.NET MVC
提问by Nick
Why might a developer use the Bind
attribute on a ViewModel object in an ASP.NET MVC project and can this have a detrimental effect an application?
为什么开发人员可能会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; }
}
采纳答案by ataravati
First of all, you don't need to create a MetadataType
class for a ViewModel. You can use data annotation attributes directly in your ViewModel. MetadataType
classes are used for Models automatically generated by EF or other ORMs, so that you can use data annotation attributes without touching the auto-generated code.
首先,您不需要MetadataType
为 ViewModel创建一个类。您可以直接在 ViewModel 中使用数据注释属性。MetadataType
类用于由 EF 或其他 ORM 自动生成的模型,以便您可以使用数据注释属性,而无需接触自动生成的代码。
The Bind
attribute does not have to be used either - unless you want to use Include
or Exclude
properties of the Bind attribute, to include or exclude properties in your Model in or from binding, respectively.
该Bind
属性没有被使用或者-除非你想使用Include
或Exclude
绑定属性的特性,包括或在您的模型或分别结合,排除特性。
For example, in the code in your question, only the Id
and Name
properties will be bound when submitting your Model from your View. Even if you have an input in your View for CustomerProductUserName
, when you submit your form, the property will always be null. This can be useful in cases like where you don't want an auto-generated ID field to be included in binding.
例如,在您问题的代码中,从您的视图提交模型时,只会绑定Id
和Name
属性。即使您在 View for 中有一个输入CustomerProductUserName
,当您提交表单时,该属性也将始终为 null。这在您不希望在绑定中包含自动生成的 ID 字段的情况下很有用。
Properties excluded from binding are also excluded from validation, because validation is done as part of model binding. Also, you may use the Bind
attribute for security reasons; for instance, when you want to make sure nothing but the properties in your model are being posted to the controller.
从绑定中排除的属性也从验证中排除,因为验证是作为模型绑定的一部分完成的。此外,Bind
出于安全原因,您可以使用该属性;例如,当您想确保将模型中的属性发送到控制器时。
回答by Abbas Amiri
You can use the Bind attribute to control how a model binder converts a request into an object. The most common way that you use the Bind attribute is when you excludean Id property from binding. For example, the Persons database table includes a column named Id that is an Identity column. Because the value of an Identity column is generated by the database automatically, you don't want to bind a form field to this property.
您可以使用 Bind 属性来控制模型绑定器如何将请求转换为对象。使用 Bind 特性的最常见方式是从绑定中排除Id 属性。例如,Persons 数据库表包含一个名为 Id 的列,它是一个 Identity 列。由于 Identity 列的值是由数据库自动生成的,因此您不希望将表单字段绑定到此属性。
On the other hand, imagine that a property of a model is especially sensitive, which a malicious user could simply append it in a URL when submitting a form. If this were done, the model binder would happily discover and use the data value in the binding process. By Bind attribute you can protect your application from this kind of attack.
另一方面,假设模型的属性特别敏感,恶意用户可以在提交表单时简单地将其附加到 URL 中。如果这样做,模型绑定器会很高兴地在绑定过程中发现并使用数据值。通过 Bind 属性,您可以保护您的应用程序免受此类攻击。
Using the Bind attribute could make problem(s) when you, for example, are going to update an entity and the ID is important for you.
例如,当您要更新实体并且 ID 对您很重要时,使用 Bind 属性可能会出现问题。
回答by Chandra Malla
The purpose of using bind attribute is to prevent attacker from assigning property value while posting of request or control what properties you want to bind.
使用 bind 属性的目的是防止攻击者在发布请求时分配属性值或控制要绑定的属性。
Let us suppose, you have a class called Member
and a create method that saves member. But you do not want user to send a value for MemberType
property.
让我们假设,您有一个被调用的类Member
和一个保存成员的创建方法。但是您不希望用户发送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);
}
Let's say for now, you are only offering Regularmember type which is the default value. You might think that you can prevent the user to send a value for MemberType property by not allowing input for MemberType
Property. But when a user posts the member object, an attacker may intercept the request and send the MemberType value in request, as
MemberId=1&FirstName=Chandra&LastName=Malla&MemberType=Premium
and save the member as a Premiummember. To prevent this, you can decorate Member
class with Bind
attribute.
假设现在,您只提供默认值的普通会员类型。您可能认为您可以通过不允许输入MemberType
Property来阻止用户发送 MemberType 属性的值。但是当用户发布成员对象时,攻击者可能会拦截该请求并在请求中发送 MemberType 值
MemberId=1&FirstName=Chandra&LastName=Malla&MemberType=Premium
,并将该成员保存为高级成员。为了防止这种情况,您可以Member
使用Bind
属性装饰类。
[Bind(Include="MemberId,FirstName,LastName")]
Class Member
{
...
or
或者
[Bind(Exclude="MemberType")]
Class Member
{
...
Now if Member
object is posted, MemberType property value will not be posted.
现在,如果Member
发布对象,则不会发布 MemberType 属性值。
If you are using ViewModel, you might not necessarily have to use bind attribute because you can omit MemberType properties in your ViewModel.
如果您使用的是 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);
}
If you do not nicely design your model and/or ViewModel and do not use bind attribute to avoid posting of property you do not want, that might have detrimental effect.
如果您没有很好地设计您的模型和/或 ViewModel 并且不使用绑定属性来避免发布您不想要的属性,那可能会产生不利影响。
回答by juFo
In addition, if you want to prevent refactoring issues when renaming properties from your model you could do something like:
此外,如果您想在从模型中重命名属性时防止出现重构问题,您可以执行以下操作:
public async Task<ActionResult> Create([Bind(Include = nameof(Foo.Bar1)+","+nameof(Foo.Bar2)+","+nameof(Foo.Bar3))] Foo fooObj)
If you now e.g. rename "Bar1" your Include Bindings will still work.
如果您现在重命名“Bar1”,则您的包含绑定仍然有效。