我正试着弄清楚为什么(数据注释)验证错误在页面首次加载时,在任何提交/帖子之前触发。但更重要的是如何解决这个问题。
读取SO和互联网,原因似乎是模型绑定在视图模型属性具有值之前触发视图模型属性的验证错误。我不确定这是否属实,实际发生了什么,但听起来是合法的。
我已经阅读了两个解决方法,听起来有点hacky: 1.在初始页面加载OR中使用控制器操作方法中的ModelState.Clear 2.在空视图模型构造函数中初始化视图模型属性。 (然而要确认这种技术)
这两种技术听起来像是解决方法。我宁愿了解正在发生的事情并正确设计我的代码。
让其他人遇到这个问题吗?如果是这样,你在做什么?
要求的代码。您可以在下面看到Property1上的数据注释验证,该验证是在初始请求(即第一页加载)上触发的。
控制器动作方法(为简单起见重构):
public ActionResult Index([Bind(Include = Property1, Property2, Property3, vmclickedSearchButton)] IndexVM vm, string Submit)
{
bool searchButtonClicked = (Submit == "Search") ? true : false;
if (searchButtonClicked)
{
PopulateUIData(vm); // Fetch data from database and pass them to VM
if (ModelState.IsValid)
{
vm.clickedSearchButton = true; // Used in the vm to avoid logic execution duing initial requests
DoWork(vm);
}
}
return View(vm);
}
// Inital request
IndexVM newVM = new IndexVM();
PopulateUIData(newVM); // Fetch data from database and pass to VM
return View(newVM);
}
设计说明: 理想情况下,我想将渲染和提交逻辑分离为单独的操作方法。 即在[HttpGet] Index()动作方法中渲染,并在[HttpPost] Index()动作方法中提交。 但由于我在View中使用ForMethod.Get,因为此方法用于搜索功能,我只能使用[HttpGet] Index操作方法。
查看模型(为简单起见重构):
public class IndexVM
{
// DropDownLists
public IEnumerable<SelectListItem> DDLForProperty1 { get; set; }
public IEnumerable<SelectListItem> DDLForProperty2 { get; set; }
public IEnumerable<SelectListItem> DDLForProperty3 { get; set; }
[Required]
public int? Property1 { get; set; }
public int? Property2 { get; set; }
public int? Property3 { get; set; }
public bool vmclickedSearchButton { get; set; }
}
注意: 视图模型非常简单。它包含下拉列表,DDL的选定属性以及其中一个属性的验证规则。
将构造函数添加到视图模型并初始化属性变通方法:
public IndexVM()
{
this.Property1 = 0;
}
答案 0 :(得分:0)
问题是您要向视图发送无效模型。
模型中的Property1
是 , 是可以为空的int
。这并不能解释验证执行的原因,而是模型无效的原因。
您的操作方法是在初始加载期间执行验证。无论http方法(get或post)如何,模型绑定都将执行验证。
由于您要求Property1
(int?
) NOT 为空,因此根据定义,您的模型在实例化时会变为无效。有几种方法可以解决这个问题(不确定哪种方法最合适)
在控制器中为HttpGet
和HttpPost
创建单独的方法。不要为HttpGet
实现绑定。
使用默认值(如您所知)
修改模型,使Property1
不可为空(即int
)。