asp.net mvc验证问题

时间:2010-09-15 18:30:30

标签: c# .net asp.net-mvc asp.net-mvc-2

这对我没有任何意义。

看看这个ViewModel:

public class SelectService
{
    [Required]
    public int? SelectedServiceId { get; set; }
}

看看这个动作:

[HttpPost]
public virtual ActionResult SelectService()
{
    TryUpdateModel(WizardContainer.SelectService, "SelectService");
    TryValidateModel(WizardContainer.SelectService, "SelectService"); // if I remove this, ModelState.IsValid will always be true


    if (ModelState.IsValid)
    {
        return RedirectToAction("OtherAction");
    }
    else
    {
        return View(WizardContainer);
    }
}

现在阅读S. Sanderson的Apress ASP.NET MVC 2 Framework中的这个例外:

  

每当使用模型绑定来填充模型对象时 - 通过将其作为操作方法接收   参数,或通过手动调用UpdateModel()或TryUpdateModel()然后DefaultModelBinder将   自动运行与其已更新的所有模型对象相关联的验证器(即,它所在的模型对象)   已在至少一个属性上设置了值)。   如果以任何其他方式更新模型对象,除非明确说明,否则不会运行其验证器   运行它们的框架。

那么,当我调用TryUpdateModel()时,为什么验证永远不会发生?要进行验证,我必须使用TryValidateModel()显式验证。

更新

这是一个非常类似的操作,在同一个控制器中按预期工作:

[HttpPost]
public virtual ActionResult Index(string nextButton)
{
    TryUpdateModel(WizardContainer.Index);

    if (nextButton != null && ModelState.IsValid)
    {
        return RedirectToAction("OtherAction");
    }
    else
    {
        return View(WizardContainer.Index);
    }
}

这是ViewModel:

public class Index
{
    [Required]
    public DateTime? SelectedServiceTime { get; set; }
}

更新2

我改变了一些东西,现在它表现得像预期的那样,但我仍然不明白为什么。

查看已编辑的操作:

[HttpPost]
public virtual ActionResult SelectService()
{
    TryUpdateModel(WizardContainer.SelectService);
    //TryValidateModel(WizardContainer.SelectService, "SelectService"); // not needed anymore

    if (ModelState.IsValid)
    {
        return RedirectToAction("OtherMethod");
    }
    else
    {
        return View(WizardContainer.SelectService);
    }
}

现在的区别仅在于我传递给TryUpdateModel()的对象是我传递给视图的对象,而不是我传递给视图的对象的属性。什么交易哟?

1 个答案:

答案 0 :(得分:0)

我在下面添加了TryUpdateModelTryValidateModel方法转换。我看到的主要区别是TryUpdateModel的返回值为ModelState.IsValid,但我发现在TryUpdateModel中没有明确执行验证程序。

TryValidateModel实际上获取验证器并执行每个验证器。您的工作和非工作案例之间必然存在一些细微差别。我不能说根本原因是什么,但在您的工作案例中,当您致电ModelState时,ModelState.Errors集合中已添加TryUpdateModel个错误。 (如果ModelState.IsValid集合中存在一个或多个错误,则ModelState.Errors会返回false。)

TryUpdateModel:

protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel: class
{
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }
    if (valueProvider == null)
    {
        throw new ArgumentNullException("valueProvider");
    }
    Predicate<string> predicate = delegate (string propertyName) {
        return BindAttribute.IsPropertyAllowed(propertyName, base.includeProperties, base.excludeProperties);
    };
    IModelBinder binder = this.Binders.GetBinder(typeof(TModel));
    ModelBindingContext context2 = new ModelBindingContext();
    context2.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(delegate {
        return base.model;
    }, typeof(TModel));
    context2.ModelName = prefix;
    context2.ModelState = this.ModelState;
    context2.PropertyFilter = predicate;
    context2.ValueProvider = valueProvider;
    ModelBindingContext bindingContext = context2;
    binder.BindModel(base.ControllerContext, bindingContext);
    return this.ModelState.IsValid;
}

TryValidateModel:

protected internal bool TryValidateModel(object model, string prefix)
{
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }
    foreach (ModelValidationResult result in ModelValidator.GetModelValidator(ModelMetadataProviders.Current.GetMetadataForType(delegate {
        return model;
    }, model.GetType()), base.ControllerContext).Validate(null))
    {
        this.ModelState.AddModelError(DefaultModelBinder.CreateSubPropertyName(prefix, result.MemberName), result.Message);
    }
    return this.ModelState.IsValid;
}