ASP.NET MVC 4“创建”页面提交导致无效的ModelState

时间:2013-06-03 20:45:50

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

我有一个问题可能仅仅是由于我缺乏ASP.NET MVC的经验,但这是我现在试图解决的问题。

我有一个Code First数据库设置,与asp.net(http://www.asp.net/mvc/tutorials/mvc-4/getting-started-with-aspnet-mvc4/intro-to-aspnet-mvc-4)上的第一个教程没有太大区别。基本上我遇到的问题是在尝试通过“创建”页面在数据库中创建新记录时,ID设置为0,这使得ModelState无效。

相关代码: 型号:

public class Evt
{
    public int ID { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string GeoDescription { get; set; }
    public decimal Longitude { get; set; }
    public decimal Latitude { get; set; }
    public DateTime Date { get; set; }
}

控制器:

[HttpPost]
public ActionResult Create(Evt evt)
{
    if (ModelState.IsValid) // This is returning false because ID is 0
    {
        db.Evts.Add(evt);
        db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(evt);
}

我可以根据请求添加View代码,但它基本上只是模型中自动生成的代码。

如果有人有任何想法,我会非常感激!

谢谢,

杰夫

编辑:我根本没有在“创建”视图中引用ID,并将其添加为隐藏的表单值也无法解决我的问题。

更新:我已经能够通过添加

来规避错误

if (!ModelState.IsValid && evt.ID == 0) ModelState.Clear();

if中的Create语句之上,但这会删除所有客户端验证,显然不理想。它确实表明,一旦它到达服务器,该记录就会以递增的ID正确插入。

4 个答案:

答案 0 :(得分:1)

看起来您正在使用您的EF Entity类作为ViewModels。建议不要这样做,因为ViewModel(封装了可读输入形式的数据内容)与实体(代表规范化的业务对象)之间没有1:1的映射,只是巧合,您可以使用简单的方法EF类作为ViewModels,但如果你这样做,最终你会遇到像这样的问题。

有一些可能的解决方案,最好是为您的页面使用专用的ViewModel。第二个是修改您的实体类以将int ID更改为int? ID,因此Model-binder不需要指定项目,第三个选项是清除任何错误的Model-state dicitonary在致电ID之前与ModelState.IsValid成员有关。

请注意,如果您继续将您的实体类用作视图模型,则您将无法使用Mass Assignment攻击(如您当前的代码所示)。这就是为什么专用的每视图ViewModel是最好的。

答案 1 :(得分:1)

正如戴说,建议的方法是不要在您的视图中直接使用您的实体。这有很多原因,但你现在正在尝试它们。

但是,如果您不打算这样做,您有几种选择。正如戴说,你可以清除模型状态,但我不喜欢这种方法。这很丑陋,实际上只是糟糕的做法。

您还可以在参数中添加[Bind(Exclude="ID")]。在这种情况下:

public ActionResult Create([Bind(Exclude="ID")] Evt evt)

我也不是很喜欢这个,但至少它并不像从控制器中的ModelState中删除项目那样难看。

您还可以添加隐藏字段。你说你这样做了并没有解决问题,但它应该有效。所以也许你做错了,比如使用错误的命名约定。我建议使用HiddenFor,并确保它在BeginForm(){}

的大括号内
@Html.HiddenFor(x => x.ID)

答案 2 :(得分:0)

如果有人在将来遇到这个问题,这可能不是你想听到的答案,但这就是我最终要做的事情。

我转而使用显式实体框架(数据库优先)而不是使用Code First。这重新生成了我的模型,随后解决了我的问题。我不确定为什么要修复它,但正如我在问题描述中所说的那样,我认为这可能是我最初意外改变的一个小设置或代码行。

我建议那些遇到此问题并且不想放弃Code First的人:尝试重构您的模型或完全删除它并创建一个具有相同属性的新模型。

抱歉,我无法提供更多帮助。

答案 3 :(得分:0)

我刚遇到这个问题,不确定是否与你相同

我使用New和Edit的相同页面,所以我有类似的东西:

@Html.HiddenFor(model => model.Code_Id)

但这仅适用于编辑,因此我添加了类似的内容:

if (ViewBag.Action != "New")
{
    @Html.HiddenFor(model => model.Code_Id)
}

和ModelState.IsValid现在为真