是否可以在 MVC 3 中打开/关闭验证数据注释
本文关键字:验证 注释 数据 MVC 是否 | 更新日期: 2024-11-08 10:28:14
>我有两个单独的视图访问同一个模型。 当我将验证器数据注释放在模型上时,它会像广告一样工作,如果留空或不在范围内,它会阻止提交数据(对于两个视图)。 但是,我有一个视图应该能够允许为属性保存空值或空值,而另一个视图需要输入或选择信息才能通过。 换句话说,我想为一个视图关闭 MODEL 中属性的验证器,并为另一个视图保留它。 下面是示例代码:
型:
[Range(1, 999, ErrorMessage = "A submittal is required")]
public int SubmittalId { get; set; }
视图 #1:
<label>@Model.AuditDoc.SubmittalsLabel.ConfigurableLabelDesc</label> @Html.ValidationMessageFor(x => x.AuditDoc.SubmittalId) @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name"))
视图 #2:
<label>@Model.AuditDoc.SubmittalsLabel.ConfigurableLabelDesc</label> @Html.DropDownListFor(x => x.AuditDoc.SubmittalId, new SelectList(Model.AuditDoc.ListOfSubmittals, "Id", "Name"))
如您所见,我想禁用视图 #2 的验证器数据注释,并将其保留为视图 #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等执行相同的操作。
我用不同的方法解决了这个问题。
诀窍不是禁用验证本身,而是在调用控制器的操作之前清除任何不适当的验证错误(因此 ModelState.IsValid 返回 true)。
如果模型(或视图模型)对象需要自定义验证,那么它实现我定义的名为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 类中,如果我想禁用(或者更确切地说:忽略)某些验证错误,那么它只需要这样做:
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。