asp.net mvc针对不同操作的不同验证规则

时间:2009-10-19 09:32:39

标签: asp.net-mvc validation

为不同的操作验证模型的最佳做法是什么,例如,创建和删除的验证规则不同?

谢谢!

澄清:我认为这需要一些澄清,因为答案似乎没有解决这个问题。

例如,

创建人物   没有使用名称,年龄和电子邮件的验证 删除人   验证Person不是Parent。商业逻辑决定父母不能被淘汰

我如何拥有这两种不同的验证方案?

7 个答案:

答案 0 :(得分:2)

据我了解,您希望更好地控制验证规则。您可以按照此处的说明手动添加验证规则:MVC 2.0 Client validation exposed这使您可以完全控制如何组织验证,哪些规则添加了哪些操作等。

答案 1 :(得分:1)

使用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, "");
                }
            }
        }
    }

答案 2 :(得分:1)

  

澄清:我认为这需要一些澄清,因为答案似乎没有解决这个问题。

     

例如,

     

创建人员名称,年龄和电子邮件未使用的验证删除人员验证人员不是父级。商业逻辑决定父母不能被淘汰

     

我如何拥有这两种不同的验证方案?

“封装变化的内容。”

实现此目的的一种方法是使用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;
    }
}

答案 3 :(得分:0)

最好使用Validator Toolkit for ASP.NET MVC

此工具包生成客户端和服务器端验证代码。

最近有一篇博文compares different validation techniques and frameworks

如果您正在使用jQuery,那么jQuery validation plugin值得使用。当然,您仍然需要编写自己的服务器端验证(或使用其他框架)。

答案 4 :(得分:0)

如果使用ASP.NET MVC 1,则将检查DataAnnotationsModelBinder扩展。 System.ComponentModel.DataAnnotations是非常有用的验证属性框架! ASP.NET MVC 2 DefaultModebinder支持它。

http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471

答案 5 :(得分:0)

如果要使用ASP.NET MVC的几个验证框架之一(xVal,Data Annotations属性等)并且仅验证特定操作的模型字段的子集,最简单的解决方案是使用{ {3}}属性。

虽然我当然可以想到一个案例,你可能只想对模型字段的一个子集进行验证(即在Create动作中),但我想不出你想要验证的情况。一个特定的领域在两个不同的行动之间完全不同。

这是一个简单的例子,将Person模型对象与Data Annotations验证器属性结合使用。 CreateUpdate操作将针对不同的模型字段进行验证。


模型

public class Person
{
  [Required]
  Int32 Id { get; set; }

  [Required]
  String FirstName {get; set;}

  [Required]
  String LastName {get; set;}
}


控制器操作

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

在上面的示例中,Create操作将完全忽略Id模型对象的Person属性。它不会尝试绑定此属性,也不会尝试对其执行任何验证。由于Person在创建时没有Id,这正是您想要的。另一方面,Update操作将绑定并验证模型的所有属性。

在method参数上指定Bind属性这一事实可能会使代码变得丑陋。但是,如果Exclude列表变长,您可以随时添加一些额外的换行符和空格,以帮助减少丑陋。

答案 6 :(得分:0)

我认为,对于这种情况,只需在DELETE的域模型(BLL)中编写一些代码来判断是否可以删除某些Person,或者在sql或sp中写入一些代码并返回值如果删除完了。