【问题标题】:MVC4: Modelstate is not valid when creating a new recordMVC4:创建新记录时模型状态无效
【发布时间】:2013-04-16 12:04:12
【问题描述】:

我尝试添加一个与大陆有链接的新国家/地区。当我按下“创建”按钮时,它不会添加新记录。我调试了我的项目,我认为这是因为 ValidState 是错误的。原因是属性“Continent”为空,但 Continent_Id 不是。 当我尝试编辑现有国家/地区时,我遇到了同样的问题。 (我在 SQL Management Studio 中使用 SQL 脚本填充了我的数据库)

有人可以帮帮我吗?

大陆类:

public class Continent
{
    public int Id { get; set; }
    [Required, MaxLength(25)]
    public string Name { get; set; }

    //Navigation
    public virtual List<Country> Countries { get; set; }
}

国家级

public class Country
{
    public int Id { get; set; }
    [Required, MaxLength(25)]
    public string Name { get; set; }
    [MaxLength(5)]
    public string Abbreviation { get; set; }

    public int Continent_Id { get; set; }

    //Navigation
    [Required, ForeignKey("Continent_Id")]
    public virtual Continent Continent { get; set; }

}

控制器类(创建函数)

  //
    // GET: /Countries/Create

    public ActionResult Create()
    {
        ViewBag.Continent_Id = new SelectList(db.Continents, "Id", "Name");
        return View();
    }

    //
    // POST: /Countries/Create

    [HttpPost]
    public ActionResult Create(Country country)
    {
       var errors = ModelState.Values.SelectMany(v => v.Errors); //to check the errors
        if (ModelState.IsValid)
        {
            db.Countries.Add(country);
            db.SaveChanges();
            return RedirectToAction("Index");
        }


        ViewBag.Continent_Id = new SelectList(db.Continents, "Id", "Name", country.Continent_Id);
        return View(country);

【问题讨论】:

    标签: asp.net-mvc asp.net-mvc-4 record modelstate


    【解决方案1】:

    就在 if (ModelState.IsValid) 行之前放这个 ModelState.Remove("v_id"); 在您的情况下,v_id 是您的主键列名称

    【讨论】:

    • 这对我有用,我不知道为什么要为新记录运行 ID 字段验证。
    • 我遇到了同样的问题,即使 id=0,modelstate 也是无效的。您的解决方案有效,谢谢
    【解决方案2】:

    我通过关闭 Continent 的必需验证来解决此问题,并将其仅设置为 Continent_Id。现在 ID 属性是必需的,但 Continent 不是。

    public class Country
    {
    public int Id { get; set; }
    [Required, MaxLength(25)]
    public string Name { get; set; }
    [MaxLength(5)]
    public string Abbreviation { get; set; }
    
    [Required] //added Required
    public int Continent_Id { get; set; }
    
    //Navigation
    [ForeignKey("Continent_Id")] //removed Required
    public virtual Continent Continent { get; set; }
    
    }
    

    感谢您的回复!

    【讨论】:

      【解决方案3】:

      我不确定,但我相信您的问题是时间问题。模型验证在绑定期间自动发生;当时,Continent 属性为空。您稍后设置该属性,但在您检查 IsValid 时不会重新评估模型状态。我看到三个选项:

      • 又快又脏:从 Continent 中移除所需的验证并改为验证 Continent_Id,在控制器中添加检查以确保从 Find() 检索到有效的 Continent。
      • 大部分工作:创建自定义模型绑定器以实际使用 Continent_Id 来检索和填充 Continent。您几乎就在这个位置上,因为同时将 Continent_Id 和 Continent 作为 Country 的属性是多余的,并且是出现不一致的机会。
      • 可能是最佳选择:让您的控制器接受一个视图模型,该模型只包含您希望从表单返回的数据并从中填充 Country 对象。

      【讨论】:

      • 您能否提供更多关于选项 3(最佳选项)的信息。
      • 我认为@Jan 涵盖了选项 3。本质上,您应该让应用程序的每一层处理对它们有意义的模型。因此,您的域模型是 Country,它具有数据存储等所需的所有字段。但是在 Web 层中,您的表单没有所有这些信息,因此您创建一个 CountryViewModel 对您拥有的数据有意义,并且根据需要在两者之间进行翻译。
      【解决方案4】:

      ModelState 无效的原因是因为您已将 Continent 属性标记为必需,但我猜在您的视图中您没有将绑定到 Continent 对象的某些属性的表单字段。

      因此,要么不根据需要标记 Continent 对象,要么提供名称为 Continent.Id 或 Continent.Name 的隐藏字段,以便模型绑定器填充 Continent 属性:

      @Html.HiddenFor(m => m.Continent.Id)
      

      但这将导致下一个问题:您已按要求标记了 Continent 类的 Name 属性,因此您也必须为该属性提供一个表单字段。

      基本问题是,您尝试将存储库类重用为视图模型类。 更好的方法是使用单独的类作为视图模型在控制器和视图之间传递数据:

      class CountryViewModel {
          public int Id { get; set; }
          [Required, MaxLength(25)]
          public string Name { get; set; }
          [MaxLength(5)]
          public string Abbreviation { get; set; }
      
          public int Continent_Id { get; set; }
      }
      

      要在 Country 和 CountryViewModel 对象之间进行映射,请使用 AutoMapper 之类的映射器。

      【讨论】:

      • 在我看来,我有一个包含大陆的下拉列表。当我选择大陆名称时,将填写 Continent_Id。但我有一个属性 Continent_Id(填写正确)和一个 Continent 属性,它是空的..
      • 是的,这就是我写的。 Continent 属性为空,因为我猜您的视图中没有任何表单字段可以将值发布到 Continent 类的某些属性。您的 Continent 类的任何属性都不会称为 Continent_Id!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-25
      • 1970-01-01
      • 2015-09-06
      • 1970-01-01
      • 2019-10-30
      • 1970-01-01
      • 2020-07-08
      相关资源
      最近更新 更多