[英]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()顯式驗證。
這是一個非常類似的操作,在同一個控制器中按預期工作:
[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; }
}
我改變了一些東西,現在它表現得像預期的那樣,但我仍然不明白為什么。
查看已編輯的操作:
[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()的對象是我傳遞給視圖的對象,而不是我傳遞給視圖的對象的屬性。 什么交易喲?
我在下面包含了TryUpdateModel
和TryValidateModel
方法的轉換。 我看到的主要區別是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.