MVC + EntityFramework +字段验证

时间:2015-05-06 15:54:21

标签: c# asp.net-mvc entity-framework asp.net-mvc-5

让我开始讲述问题:当我提交我的View时,我的Action从一个名为Customer的类中接收一个对象,该对象具有整数但可以为空的外键。

该类由EF Designer生成,我的数据库结构如下(我希望放一张图片,但是,它告诉我需要10个声誉):

Customer (Table)
  CityId -> City (Table)
            CityId
            StateId -> State (Table)
                       StateId
                       CountryId -> Country (Table)
                                    CountryId

恢复,我的客户必须在一个城市,必须与一个必须与国家相关的州相关联。

另一方面,我的视图中有3个下拉列表: 1选择国家,另一个选择所选国家的一个州,第三个选择国家。 当我选择国家,视图(通过JSON)时,用状态等填写另一个下拉列表,因此,显然我只保存了CityId。

问题,当我尝试提交时,MVC向我展示了以下验证:

The CountryId field is required.
The StateId field is required.
The CityId field is required.

发生这种情况是因为这些字段是Int32。所以,我做的第一件事就是改变,在EF Designer中这些字段可以为空(因为我想通过 ModelState.AddModelError 进行个人验证)。

我还将Multiplicity更改为0..1。

在数据库中,这些字段必须是不可为空的。

但是现在,我收到以下错误:错误3错误3031:从第1074行开始映射片段时出现问题:表Cidades中的非可空列Cidades.EstId映射到可以为空的实体属性。

解决此问题的最佳方法是什么?

提前致谢

2 个答案:

答案 0 :(得分:1)

问题很容易解决:设计视图,以便发布的表单只包含您尝试存储在数据库中的实体的属性(Customer)。

这意味着:

  • 您必须仅使用Html Helpers创建与Customer属性相关的控件,而不是其他实体属性。即不要使用Html Helpers为" Customer.City.CityId"创建控件,但是对于" Customer.CityId"。通过这种方式,您可以确保仅将Customer属性发布到控制器操作中。
  • (我自己,但是)你必须避免创建与任何其他相关实体相关的控制:城市,州和国家。此控件应该是纯HTML对象。您只需稍后使用JavaScript访问它们(例如,加载级联列表)。必须与任何属性相关的唯一控件是包含城市的下拉列表(<select>),该城市必须具有Customer.CityId名称,而不是Customer.City.CityId

如果您这样做,当您发布表单时,您只会发布Customer对象,因此控制器中的帖子操作应仅接收Customer参数。那么EF不会对任何其他实体进行任何验证,只是因为它们不存在而且您将摆脱这个问题。

关于验证:根据您的配置,验证可以在客户端和服务器上进行。如果采取这些预防措施,您将避免双方的问题。不要改变你的模型接受空值!这是一个糟糕的黑客!

注意:由于您没有显示您的代码,我猜测它的外观或多或少。如果我的回答不够清楚,请更新您的问题,让我知道@JotaBe的评论

答案 1 :(得分:0)

我修复了删除MVC强加的主要验证的问题:

ModelState.Remove("City.State.CountryId");
ModelState.Remove("City.StateId");
ModelState.Remove("CityId");

但是,@ JotaBe给出的提示也是一个有趣的解决方案。