繁体   English   中英

asp.net mvc验证问题

[英]asp.net mvc validation problem

这对我没有任何意义。

看看这个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()显式验证。

UPDATE

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

[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()的对象是我传递给视图的对象,而不是我传递给视图的对象的属性。 什么交易哟?

我在下面包含了TryUpdateModelTryValidateModel方法的转换。 我看到的主要区别是TryUpdateModel的返回是ModelState.IsValid ,但我看不到TryUpdateModel验证器的显式执行。

TryValidateModel实际上获取验证器并执行每个验证器。 您的工作和非工作案例之间必然存在一些细微差别。 我不能说根本原因是什么,但在您的工作案例中,当您调用TryUpdateModel时,已经将ModelState错误添加到ModelState.Errors集合中。 (如果ModelState.Errors集合中存在一个或多个错误, ModelState.IsValid将返回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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM