2013-04-16 55 views
0

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

有人可以帮助我吗?

洲类:

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; } 

} 

Controller类(创建函数)

// 
    // 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); 

回答

0

我通过将必需的验证置于Continent之后解决了此问题,并仅将它设置在Continent_Id上。现在ID属性是必需的,但欧洲大陆不是。

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; } 

} 

感谢您的回复!

0

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

  • 快速和肮脏的:采取必要的验证过大陆和验证Continent_Id而是添加在控制器检查,以确保()的有效大陆从查找检索。
  • 大部分工作:创建一个自定义模型联编程序以实际使用Continent_Id来检索和填充Continent。由于Continent_Id和Continent作为Country的属性是多余的,并且存在不一致的机会,因此您几乎在这一点上。
  • 可能是最好的选择:让你的控制器接受一个视图模型,它只包含你希望从表单返回的数据并从中填充一个Country对象。
+0

您能否请求给出选项3(最佳选项)的更多信息。 –

+0

我认为@Jan有覆盖选项3。从本质上讲,你应该让应用程序的每一层处理一个对他们有意义的模型。因此,您的域模型是Country,它具有数据存储所需的所有字段等。但是,在Web层中,您的表单没有所有这些信息,因此您需要创建一个CountryViewModel,这对您所拥有的数据有意义,必要时在两者之间进行转换。 – rpmcnally

-1

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

所以要求要么不标注大陆对象或提供的隐藏字段与Continent.Id或Continent.Name的名称,以便该模型粘结剂将填充大地财产:

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

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

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

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; } 
} 

自己的国家和CountryViewModel对象之间进行映射使用像AutoMapper一个映射器。

+0

在我的观点中,我有一个大陆下拉列表。当我选择大陆名称时,Continent_Id将被填充。但是我有一个属性Continent_Id(正确填写)和Continent属性,它是空的。 –

+0

是的,那就是我写的。 Continent属性为null,因为我想你的视图中没有任何表单域,它向Continent类的某些属性发布了值。您的Continent类没有任何属性称为Continent_Id! – Jan

+0

谢谢!这就说得通了 ! –

2

只是前行如果(ModelState.IsValid)把这个 ModelState.Remove( “v_id”); 其中v_id是您的案例中的主键列名称