我有以下视图模型:
public class CreateCaseViewModel
{
[Required]
public string Subject { get; set; }
[Required]
[DisplayName("Post Content")]
[UIHint("ForumEditor"), AllowHtml]
[DataType(DataType.MultilineText)]
public string PostContent { get; set; }
// some other dropdown properties
}
以下控制器操作:
[HttpPost]
[ValidateAntiForgeryToken]
[ValidateInput(false)]
public ActionResult Create(CreateCaseViewModel viewModel, FormCollection collection)
{
// Re-populate dropdowns
viewModel.Categories = _unitOfWork.CategoryRepository.GetCategories();
viewModel.Subject = collection["Subject"];
viewModel.PostContent = collection["Description"];
try
{
if (ModelState.IsValid)
{
// Do stuff
}
}
catch (DataException dex )
{
throw new ApplicationException("Something :", dex);
}
return View(viewModel);
}
我正在从FormCollection中的值手动将值分配给PostContent,如上面的代码所示。但是我仍然继续让模型状态无效 - 我返回到视图时出现验证错误,说“帖子内容字段是必需的”
为什么modelstate无效?
答案 0 :(得分:1)
模型在传递给控制器操作之前已经过验证。修改模型不会改变它。
您需要调用ModelState.Clear()
后跟Controller.TryValidateModel(model)
来重新验证模型并重置IsValid属性。
答案 1 :(得分:1)
当您提交表单时,模型绑定器将读取已发布的请求数据并将其映射到您的方法参数。之后,模型验证框架将进行验证。它不会看你的FormCollection这样做。因此,在您的情况下,您的模型验证失败,因为根据您的视图模型,它期望PostContent
属性的值,并且它在那里不可用。您设置其值的操作方法代码稍后执行(此时已经发生模型验证)。
您的选项是,使用您的视图模型属性名称标准化输入元素名称(将PostContent
重命名为Description
,反之亦然)
public class CreateCaseViewModel
{
[Required]
public string Subject { get; set; }
[Required]
[DisplayName("Post Content")]
[UIHint("ForumEditor"), AllowHtml]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
}
现在让模型绑定器将请求主体映射到视图模型参数。从操作方法
中的FormCollection中删除手动分配或您可以创建一个新的custom model binder,为您执行自定义映射(与您在操作方法中执行的操作相同)。
我会选择选项一。让默认的模型绑定器来处理它。