简体   繁体   English

asp.net mvc验证问题

[英]asp.net mvc validation problem

This doesn't make any sense to me. 这对我没有任何意义。

Look at this ViewModel: 看看这个ViewModel:

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

Look at this Action: 看看这个动作:

[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);
    }
}

Now read this exceprt from Apress ASP.NET MVC 2 Framework by S. Sanderson: 现在阅读S. Sanderson的Apress ASP.NET MVC 2 Framework中的这个例外:

Whenever you use model binding to populate a model object—either by receiving it as an action method parameter, or by calling UpdateModel() or TryUpdateModel() manually—then DefaultModelBinder will automatically run the validators associated with all model objects that it has updated (ie, ones where it has set a value on at least one property). 无论何时使用模型绑定来填充模型对象(通过将其作为操作方法参数接收),或通过手动调用UpdateModel()或TryUpdateModel(),DefaultModelBinder将自动运行与其已更新的所有模型对象关联的验证器(即,它已在至少一个财产上设定值的那些)。 If you update a model object in any other way, its validators will not be run unless you explicitly tell the framework to run them. 如果以任何其他方式更新模型对象,则除非您明确告诉框架运行它们,否则将不会运行其验证程序。

So, why then is validation never occuring when I call TryUpdateModel()? 那么,当我调用TryUpdateModel()时,为什么验证永远不会发生? To get validation to occur, I have to explicitly validate using TryValidateModel(). 要进行验证,我必须使用TryValidateModel()显式验证。

UPDATE UPDATE

Here is a very similar action in the same controller that works as expected: 这是一个非常类似的操作,在同一个控制器中按预期工作:

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

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

And here is it's ViewModel: 这是它的ViewModel:

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

Update 2 更新2

I changed some things and now it behaves as expected, but I still don't understand why. 我改变了一些东西,现在它表现得像预期的那样,但我仍然不明白为什么。

Look at the edited action: 查看已编辑的操作:

[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);
    }
}

The difference now being only that the object that I am passing to TryUpdateModel() is the object I am passing to the view instead of being a property of the object that I pass to the view. 现在的区别仅在于我传递给TryUpdateModel()的对象是我传递给视图的对象,而不是我传递给视图的对象的属性。 What the deal yo? 什么交易哟?

I've included both the TryUpdateModel and TryValidateModel method decompilations below. 我在下面包含了TryUpdateModelTryValidateModel方法的转换。 The primary difference I see is that the return of TryUpdateModel is ModelState.IsValid , but I see no explicit execution of the validators in TryUpdateModel . 我看到的主要区别是TryUpdateModel的返回是ModelState.IsValid ,但我看不到TryUpdateModel验证器的显式执行。

TryValidateModel actually gets the validators and executes each one. TryValidateModel实际上获取验证器并执行每个验证器。 There must be some subtle difference between your working and non-working cases. 您的工作和非工作案例之间必然存在一些细微差别。 I can't say what the root cause is, but in your working case there are already ModelState errors added to the ModelState.Errors collection when you call TryUpdateModel . 我不能说根本原因是什么,但在您的工作案例中,当您调用TryUpdateModel时,已经将ModelState错误添加到ModelState.Errors集合中。 ( ModelState.IsValid returns false if there are one or more errors in the ModelState.Errors collection.) (如果ModelState.Errors集合中存在一个或多个错误, ModelState.IsValid将返回false。)

TryUpdateModel: 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: 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