在ASP.NET MVC3中验证表单时,是否有任何方法可以忽略某些属性(在POCO上)?

Pur*_*ome 21 c# validation asp.net-mvc asp.net-mvc-3

我有一个注册新用户注册向导.当我尝试转到第二页时,我得到验证错误,因为我的User对象还没有完全填充.有什么办法可以告诉每个人ActionMethod在检查支票时忽略一些属性ModelState.IsValid吗?

例如.(简体,pseduo代码)

public class User
{
   [Required]
   public string Name; // Asked on page 1.
   [Required]
   public int Age; // Asked on page 1.
   [Required]
   public string Avatar;  // Asked on Page 2.
}
Run Code Online (Sandbox Code Playgroud)

它抱怨说阿凡达是必需的/不能为空.但我没有机会要求用户填写此内容,直到下一页.

在第1页中是否可以要求忽略此检查?

Lin*_*ron 20

您可以使用绑定属性:http://ittecture.wordpress.com/2009/05/01/tip-of-the-day-199-asp-net-mvc-defining-model-binding-explicitly/

更好的选择是使用ViewModels.

http://weblogs.asp.net/shijuvarghese/archive/2010/02/01/view-model-pattern-and-automapper-in-asp-net-mvc-applications.aspx

  • @awirgley这里的问题是没有得到验证错误.它得到了错误的验证错误.您为向导的每个部分创建一个ViewModel,因为它们只是不同的视图. (4认同)

Dar*_*oll 20

在操作中,只删除尚未检查的项目的错误.然后,这使您的模型对已检查的项目有效

foreach (var error in ModelState["Avatar"].Errors)
 {
      ModelState["Avatar"].Errors.Remove(error);
 }
Run Code Online (Sandbox Code Playgroud)

要么

ModelState["Avatar"].Errors.Clear();
Run Code Online (Sandbox Code Playgroud)


awr*_*ley 5

这在史蒂夫桑德森的asp.net mvc 2书,第486页中讨论过.

创建一个继承自ActionFilterAttribute的自定义属性ValidateIncomingValuesOnlyAttribute,并将其应用于控制器类.

覆盖OnActionExecuting方法:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{

var modelState = filterContext.Controller.ViewData.ModelState;
var incomingValues = filterContext.Controller.ValueProvider;

var keys = modelState.Keys.Where(x => !incomingValues.ContainsPrefix(x));
foreach(var key in keys)
{
modelState[key].Errors.Clear();
}
}
Run Code Online (Sandbox Code Playgroud)

这样,您只能验证与向导中每个步骤相关的数据.然后,您需要一个没有数据输入的确认页面,以将验证的数据发送到服务器.

但最重要的是,阅读史蒂夫桑德森的书,它为这个和你的另一个问题提供了一个有效的解决方案.

附录:

如果您决定映射到viewmodel而不是上面的内容,请小心,因为您要么必须:

一个.不使用验证dataannotation属性装饰viewmodel属性,在这种情况下,只有在用户填写整个向导并尝试提交到数据库后才会进行验证.从用户的角度来看,这将非常简单......

湾 否则,您仍然必须使用S Sanderson描述的技术,即清除与当前步骤中的字段无关的任何验证错误.

我没有看到接受的答案是回答问题.


小智 5

要忽略ModelState的属性,这是最简单的代码。

if (ModelState["PropertyName"] != null) ModelState["PropertyName"].Errors.Clear();
Run Code Online (Sandbox Code Playgroud)