簡體   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