【问题标题】:Asp MVC 5 - ModelState is Invalid?Asp MVC 5 - ModelState 无效?
【发布时间】:2018-04-10 00:01:38
【问题描述】:

我有以下视图模型:

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 is invalid - 我返回到视图并显示验证错误说“需要发布内容字段”

为什么模型状态无效?

【问题讨论】:

  • 为什么要使用 FormCollection 并手动分配它?在您的视图模型中创建一个名为 Description 的新属性,并让模型绑定为您处理它
  • @Shyju 它是一个动态表单,表单结构存储为 xml,所以我无法创建专用的视图模型,因为我不知道表单上有多少字段或它们是什么叫。但是有一些必填字段,例如 Subject 和 PostContent,我想将它们映射到视图模型。这些字段将作为名称值对在数据库中进行排序。

标签: asp.net-mvc validation viewmodel modelstate


【解决方案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,它会为您执行自定义映射(与您在操作方法中所做的相同)。

我会选择选项一。让默认模型绑定器处理它。

【讨论】:

  • 是否区分大小写,即public string Description { get; set; }映射到元素名称description?
  • 区分大小写。 description 应该很好地绑定到 Description
【解决方案2】:

模型在传递给您的控制器操作之前经过验证。修改模型并不会改变这一点。

您需要调用ModelState.Clear() 后跟Controller.TryValidateModel(model) 以重新验证模型并重置 IsValid 属性。

【讨论】:

  • 那么它是如何验证Subject 字段的呢?是因为在表单上我有一个名为Subject 的字段,而在实际表单中我没有一个名为PostContent 的字段。如果我要在表单中将 Description 字段重命名为 PostContent 也应该可以工作?
  • 好一个菲利普。你的提示让我回到了正确的轨道上。
  • 模型已验证,但您的必填字段 PostContent 为空。所以 IsValid 设置为 false。然后设置 PostContent,但这不会改变任何验证。您必须手动重新验证模型才能更改 IsValid 设置。
猜你喜欢
  • 2019-08-01
  • 2017-05-30
  • 2016-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
相关资源
最近更新 更多