What is the best practice for validating my model for different actions, for example, different validation rules for creating and deleting?
验证我的模型用于不同操作的最佳实践是什么,例如,用于创建和删除的不同验证规则?
Thanks!
Clarification: I think this needs some clarification because the answers don't seem to be addressing the question.
澄清:我认为这需要一些澄清,因为答案似乎没有解决问题。
For example,
Create Person Validates that has name, age and email is not in use Delete Person Validates that the Person isn't a Parent. Business logic dictates that Parents can't be eliminated
创建人员姓名,年龄和电子邮件未使用的验证删除人员验证人员不是父级。商业逻辑规定父母不能被淘汰
How do I have these two different validation scenarios?
我如何拥有这两种不同的验证方案?
7 个解决方案
#1
2
As i understand you want more control on your validation rules. You can manually add validation rules as described here: MVC 2.0 Client validation exposed This gives you full control on how to organize you validation, which rule add on which action, etc.
据我所知,您希望更好地控制验证规则。您可以手动添加验证规则,如下所述:暴露MVC 2.0客户端验证这使您可以完全控制如何组织验证,哪些规则添加了哪些操作等。
#2
1
Use a validation library like FluentValidation or NHibernate Validators to do the validation. Move this code into a model binder so that whenever a model is passed it does validation automatically. You can look at the following model binder which works with FluentValidation
使用FluentValidation或NHibernate Validators等验证库进行验证。将此代码移动到模型绑定器中,这样无论何时传递模型,它都会自动进行验证。您可以查看以下使用FluentValidation的模型绑定器
public class FluentValidationModelBinder : DefaultModelBinder {
private readonly IValidatorFactory _validatorFactory;
public FluentValidationModelBinder(IValidatorFactory validatorFactory) {
_validatorFactory = validatorFactory;
}
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
var model = bindingContext.Model;
base.OnModelUpdated(controllerContext, bindingContext);
IValidator validator = _validatorFactory.GetValidator(bindingContext.ModelType);
if (validator != null) {
var result = validator.Validate(model);
if (!result.IsValid) {
result.AddToModelState(bindingContext.ModelState, "");
}
}
}
}
#3
1
Clarification: I think this needs some clarification because the answers don't seem to be addressing the question.
澄清:我认为这需要一些澄清,因为答案似乎没有解决问题。
For example,
Create Person Validates that has name, age and email is not in use Delete Person Validates that the Person isn't a Parent. Business logic dictates that Parents can't be eliminated
创建人员姓名,年龄和电子邮件未使用的验证删除人员验证人员不是父级。商业逻辑规定父母不能被淘汰
How do I have these two different validation scenarios?
我如何拥有这两种不同的验证方案?
"Encapsulate what varies."
“封装变化的东西。”
One way to accomplish this is using the Command pattern, and applying your validation to the Command instead of the Entity. Here's a simple example without using any validation framework, but the idea is the same.
实现此目的的一种方法是使用Command模式,并将验证应用于Command而不是Entity。这是一个不使用任何验证框架的简单示例,但这个想法是一样的。
public class Blub
{
public int BlubId { get; set; }
public string Name { get; set; }
public bool SomeBlockingCondition { get; set; }
}
public class BlubEditController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Rename(int blubId)
{
var ctx = new DataContext();
var blub = ctx.Blubs.Single(o => o.BlubId==blubId);
return ShowRenameForm(blub);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Rename(int blubId, RenameCommand cmd)
{
var ctx = new DataContext();
var blub = ctx.Blubs.Single(o => o.BlubId==blubId);
cmd.Subject = blub;
if (cmd.Validate(ModelState, "cmd."))
{
cmd.Execute();
ctx.SubmitChanges();
return RedirectToAction("Show", new { blubId = blubId });
}
else
{
return ShowRenameForm(blub);
}
}
}
public class RenameCommand
{
public Blub Subject { get; set; }
public string Name { get; set; }
public bool Validate(ModelStateDictionary modelState, string prefix)
{
if (Subject.SomeBlockingCondition)
{
modelState.AddModelError(prefix + "SomeBlockingCondition", "No!");
return false; // Optional shortcut return to prevent further validation.
}
if (String.IsNullOrEmpty(this.Name))
{
modelState.AddModelError(prefix + "Name", "Seriously, no.");
}
return modelState.IsValid;
}
public void Execute()
{
Subject.Name = this.Name;
}
}
#4
0
It's probably best to use the Validator Toolkit for ASP.NET MVC
最好使用Validator Toolkit for ASP.NET MVC
This toolkit generates client side and server side validation code.
此工具包生成客户端和服务器端验证代码。
Here is a recent blog post that compares different validation techniques and frameworks.
这是最近的博客文章,比较了不同的验证技术和框架。
If you're using jQuery then the jQuery validation plugin is worth using. Of course you still have to write your own server-side validation (or use another framework for it).
如果您正在使用jQuery,则jQuery验证插件值得使用。当然,您仍然需要编写自己的服务器端验证(或使用其他框架)。
#5
0
If you use ASP.NET MVC 1,you will check DataAnnotationsModelBinder extension. System.ComponentModel.DataAnnotations is very useful validation attribute framework! And ASP.NET MVC 2 DefaultModebinder supported it.
如果使用ASP.NET MVC 1,则将检查DataAnnotationsModelBinder扩展。 System.ComponentModel.DataAnnotations是非常有用的验证属性框架! ASP.NET MVC 2 DefaultModebinder支持它。
http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471
#6
0
If you want to use one of the several validation frameworks for ASP.NET MVC (xVal, Data Annotations attributes, etc) and only validate a subset of a model's fields for a particular action, the easiest solution is to use the [Bind]
attribute.
如果要使用ASP.NET MVC的几个验证框架之一(xVal,Data Annotations属性等)并且仅验证特定操作的模型字段的子集,最简单的解决方案是使用[Bind]属性。
While I can certainly think of a case where you might only want to validate against a subset of a model's fields (i.e. in a Create
action), I cannot think of a case where you would want the validations for a particular field to be completely different between two different actions.
虽然我当然可以想到一个案例,您可能只想验证模型字段的子集(即在Create操作中),但我想不出您希望特定字段的验证完全不同的情况两种不同的行为之间。
Here is a simple example, using a Person model object in conjunction with Data Annotations validator attributes. The Create
and Update
action will be validating against a different set of the model's fields.
下面是一个简单的示例,将Person模型对象与Data Annotations验证器属性结合使用。 “创建和更新”操作将针对不同的模型字段集进行验证。
Model:
public class Person
{
[Required]
Int32 Id { get; set; }
[Required]
String FirstName {get; set;}
[Required]
String LastName {get; set;}
}
Controller Actions:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create( [Bind(Exclude = "Id")] Person person )
{
// this action will not perform any validation checks against the Id property of the model
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update( Person person )
{
// this action will perform validation checks against all model properties, including Id
}
In the above example, the Create
action will completely ignore the Id
attribute of the Person
model object. It will not attempt to bind this property, nor will it attempt to perform any validations against it. Since a Person would not have an Id at the time of creation, this is exactly what you want. The Update
action, on the other hand, will bind and validate against all properties of the model.
在上面的示例中,Create操作将完全忽略Person模型对象的Id属性。它不会尝试绑定此属性,也不会尝试对其执行任何验证。由于Person在创建时没有Id,这正是您想要的。另一方面,Update操作将绑定并验证模型的所有属性。
The fact that the Bind
attribute is specified on the method argument can make the code a bit on the ugly side. However, if the Exclude
list gets long, you can always add some additional line breaks and whitespace to help reduce the ugliness.
在方法参数上指定Bind属性的事实可能使代码有点丑陋。但是,如果Exclude列表变长,您可以随时添加一些额外的换行符和空格以帮助减少丑陋。
#7
0
I think, for this case, just write some code in the domain model (BLL) of DELETE to judge if some Person can be deleted, or write some code in the sql or sp and return a value to dedicate if the delete is done.
我认为,对于这种情况,只需在DELETE的域模型(BLL)中编写一些代码来判断是否可以删除某些Person,或者在sql或sp中编写一些代码,如果删除完成则返回一个值来专用。
#1
2
As i understand you want more control on your validation rules. You can manually add validation rules as described here: MVC 2.0 Client validation exposed This gives you full control on how to organize you validation, which rule add on which action, etc.
据我所知,您希望更好地控制验证规则。您可以手动添加验证规则,如下所述:暴露MVC 2.0客户端验证这使您可以完全控制如何组织验证,哪些规则添加了哪些操作等。
#2
1
Use a validation library like FluentValidation or NHibernate Validators to do the validation. Move this code into a model binder so that whenever a model is passed it does validation automatically. You can look at the following model binder which works with FluentValidation
使用FluentValidation或NHibernate Validators等验证库进行验证。将此代码移动到模型绑定器中,这样无论何时传递模型,它都会自动进行验证。您可以查看以下使用FluentValidation的模型绑定器
public class FluentValidationModelBinder : DefaultModelBinder {
private readonly IValidatorFactory _validatorFactory;
public FluentValidationModelBinder(IValidatorFactory validatorFactory) {
_validatorFactory = validatorFactory;
}
protected override void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
var model = bindingContext.Model;
base.OnModelUpdated(controllerContext, bindingContext);
IValidator validator = _validatorFactory.GetValidator(bindingContext.ModelType);
if (validator != null) {
var result = validator.Validate(model);
if (!result.IsValid) {
result.AddToModelState(bindingContext.ModelState, "");
}
}
}
}
#3
1
Clarification: I think this needs some clarification because the answers don't seem to be addressing the question.
澄清:我认为这需要一些澄清,因为答案似乎没有解决问题。
For example,
Create Person Validates that has name, age and email is not in use Delete Person Validates that the Person isn't a Parent. Business logic dictates that Parents can't be eliminated
创建人员姓名,年龄和电子邮件未使用的验证删除人员验证人员不是父级。商业逻辑规定父母不能被淘汰
How do I have these two different validation scenarios?
我如何拥有这两种不同的验证方案?
"Encapsulate what varies."
“封装变化的东西。”
One way to accomplish this is using the Command pattern, and applying your validation to the Command instead of the Entity. Here's a simple example without using any validation framework, but the idea is the same.
实现此目的的一种方法是使用Command模式,并将验证应用于Command而不是Entity。这是一个不使用任何验证框架的简单示例,但这个想法是一样的。
public class Blub
{
public int BlubId { get; set; }
public string Name { get; set; }
public bool SomeBlockingCondition { get; set; }
}
public class BlubEditController : Controller
{
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Rename(int blubId)
{
var ctx = new DataContext();
var blub = ctx.Blubs.Single(o => o.BlubId==blubId);
return ShowRenameForm(blub);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Rename(int blubId, RenameCommand cmd)
{
var ctx = new DataContext();
var blub = ctx.Blubs.Single(o => o.BlubId==blubId);
cmd.Subject = blub;
if (cmd.Validate(ModelState, "cmd."))
{
cmd.Execute();
ctx.SubmitChanges();
return RedirectToAction("Show", new { blubId = blubId });
}
else
{
return ShowRenameForm(blub);
}
}
}
public class RenameCommand
{
public Blub Subject { get; set; }
public string Name { get; set; }
public bool Validate(ModelStateDictionary modelState, string prefix)
{
if (Subject.SomeBlockingCondition)
{
modelState.AddModelError(prefix + "SomeBlockingCondition", "No!");
return false; // Optional shortcut return to prevent further validation.
}
if (String.IsNullOrEmpty(this.Name))
{
modelState.AddModelError(prefix + "Name", "Seriously, no.");
}
return modelState.IsValid;
}
public void Execute()
{
Subject.Name = this.Name;
}
}
#4
0
It's probably best to use the Validator Toolkit for ASP.NET MVC
最好使用Validator Toolkit for ASP.NET MVC
This toolkit generates client side and server side validation code.
此工具包生成客户端和服务器端验证代码。
Here is a recent blog post that compares different validation techniques and frameworks.
这是最近的博客文章,比较了不同的验证技术和框架。
If you're using jQuery then the jQuery validation plugin is worth using. Of course you still have to write your own server-side validation (or use another framework for it).
如果您正在使用jQuery,则jQuery验证插件值得使用。当然,您仍然需要编写自己的服务器端验证(或使用其他框架)。
#5
0
If you use ASP.NET MVC 1,you will check DataAnnotationsModelBinder extension. System.ComponentModel.DataAnnotations is very useful validation attribute framework! And ASP.NET MVC 2 DefaultModebinder supported it.
如果使用ASP.NET MVC 1,则将检查DataAnnotationsModelBinder扩展。 System.ComponentModel.DataAnnotations是非常有用的验证属性框架! ASP.NET MVC 2 DefaultModebinder支持它。
http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471
#6
0
If you want to use one of the several validation frameworks for ASP.NET MVC (xVal, Data Annotations attributes, etc) and only validate a subset of a model's fields for a particular action, the easiest solution is to use the [Bind]
attribute.
如果要使用ASP.NET MVC的几个验证框架之一(xVal,Data Annotations属性等)并且仅验证特定操作的模型字段的子集,最简单的解决方案是使用[Bind]属性。
While I can certainly think of a case where you might only want to validate against a subset of a model's fields (i.e. in a Create
action), I cannot think of a case where you would want the validations for a particular field to be completely different between two different actions.
虽然我当然可以想到一个案例,您可能只想验证模型字段的子集(即在Create操作中),但我想不出您希望特定字段的验证完全不同的情况两种不同的行为之间。
Here is a simple example, using a Person model object in conjunction with Data Annotations validator attributes. The Create
and Update
action will be validating against a different set of the model's fields.
下面是一个简单的示例,将Person模型对象与Data Annotations验证器属性结合使用。 “创建和更新”操作将针对不同的模型字段集进行验证。
Model:
public class Person
{
[Required]
Int32 Id { get; set; }
[Required]
String FirstName {get; set;}
[Required]
String LastName {get; set;}
}
Controller Actions:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create( [Bind(Exclude = "Id")] Person person )
{
// this action will not perform any validation checks against the Id property of the model
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Update( Person person )
{
// this action will perform validation checks against all model properties, including Id
}
In the above example, the Create
action will completely ignore the Id
attribute of the Person
model object. It will not attempt to bind this property, nor will it attempt to perform any validations against it. Since a Person would not have an Id at the time of creation, this is exactly what you want. The Update
action, on the other hand, will bind and validate against all properties of the model.
在上面的示例中,Create操作将完全忽略Person模型对象的Id属性。它不会尝试绑定此属性,也不会尝试对其执行任何验证。由于Person在创建时没有Id,这正是您想要的。另一方面,Update操作将绑定并验证模型的所有属性。
The fact that the Bind
attribute is specified on the method argument can make the code a bit on the ugly side. However, if the Exclude
list gets long, you can always add some additional line breaks and whitespace to help reduce the ugliness.
在方法参数上指定Bind属性的事实可能使代码有点丑陋。但是,如果Exclude列表变长,您可以随时添加一些额外的换行符和空格以帮助减少丑陋。
#7
0
I think, for this case, just write some code in the domain model (BLL) of DELETE to judge if some Person can be deleted, or write some code in the sql or sp and return a value to dedicate if the delete is done.
我认为,对于这种情况,只需在DELETE的域模型(BLL)中编写一些代码来判断是否可以删除某些Person,或者在sql或sp中编写一些代码,如果删除完成则返回一个值来专用。