是否可以在MVC 3中打开/关闭validation数据注释?

我有两个单独的VIEWS访问相同的MODEL。 当我在模型上放置validation器数据注释时,它按照公布的方式工作,如果留空或不在范围内,则阻止提交数据(对于两个视图)。 但是,我有一个视图应该能够允许为属性保存空值或空值,而另一个视图需要输入或选择信息才能通过它。 换句话说,我想关闭一个视图中MODEL内属性的validation器,并将其保留为另一个视图。 这是示例代码:

模型:

[Range(1, 999, ErrorMessage = "A submittal is required")] public int SubmittalId { get; set; } 

视图#1:

   @Html.ValidationMessageFor(x => x.AuditDoc.SubmittalId) @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name")) 

视图#2:

   @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name")) 

正如您所看到的,我想为View#2禁用该validation器数据注释,并将其保留为View#1。

这不可能通过默认的数据注释集来实现。但是,您可以选择使用2个单独的视图模型或编写自己的validationAttribute。

我写了一次..虽然我厌恶使用它..

 public class RequiredOnAttribute : ValidationAttribute { public string[] URLs { get; set; } public override bool IsValid(object value) { if (URLs.Contains(System.Web.HttpContext.Current.Request.Url.AbsolutePath)) { if (string.IsNullOrEmpty(value as string)) { return false; } } return true; } } 

用法:

 [RequiredOn(URLs = new string[] { "/create", "/edit" })] public string MyModelField { get; set; } 

你可以为Range,RegEx等做同样的事情。

我用不同的方法解决了这个问题。

诀窍不是禁用validation本身,而是在调用控制器的操作之前清除任何不适当的validation错误(因此ModelState.IsValid返回true)。

如果Model(或ViewModel)对象需要自定义validation,那么它实现了我定义的名为ICustomValidation的接口,如下所示:

 public interface ICustomValidation { void PerformValidation(ModelStateDictionary modelState); } 

我的BaseController类(我的所有控制器都是子类)都有这个方法覆盖:

 protected override void OnActionExecuting(ActionExecutingContext filterContext) { base.OnActionExecuting(filterContext); // Unfortunately it seems this is the only way to get the Model object if( filterContext.ActionParameters.ContainsKey("model") ) { Object model = filterContext.ActionParameters["model"]; ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState; // ViewData.Model always returns null at this point. ICustomValidation modelValidation = model as ICustomValidation; if( modelValidation != null ) { modelValidation.PerformValidation( modelState ); } } } 

所以在示例ViewModel类中,如果我想禁用(或者更确切地说:忽略)某些validation错误,那么它只需要这样做:

 public class SomeModel : ICustomValidation { [Required] public Boolean NamePresent { get; set; } [Required] public String Name { get; set; } public void PerformValidation(ModelStateDictionary modelState) { if( !NamePresent ) dict.Remove("Name"); } } 

在我的实际代码中,有一些逻辑可以在模型递归和按前缀方法中清除ModelStateDictionary,从而使其保持健壮。

我的解决方案与您的问题不完全匹配,但使用类似的方法,您应该能够让它为您工作。

我也建议使用不同的视图模型对象。 本文有一个很好的例子,说明如何干净利落地实现它http://lostechies.com/jimmybogard/2009/06/30/how-we-do-mvc-view-models/

或者,您可以简单地不在控制器上调用ModelState.IsValid。