MVC4:Modelstate在创建新记录时无效

时间:2013-04-16 12:04:12

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

我尝试添加一个新的国家/地区,其中包含指向大陆的链接。当我按下“创建”按钮时,它不会添加新记录。我调试了我的项目,我认为这是因为ValidState是false。这样做的原因是属性“Continent”为null,但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);

4 个答案:

答案 0 :(得分:3)

在行 if(ModelState.IsValid)之前放置此内容 ModelState.Remove( “v_id”); 其中v_id是您的主键列名称

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

我通过将所需的验证放在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 :(得分:-1)

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

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

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

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

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

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等映射器。