2

我有一个问题可能只是由于我缺乏 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);
}

我也可以根据要求添加视图代码,但它基本上只是模型自动生成的代码。

如果有人有任何想法,我将不胜感激!

谢谢,

杰夫

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

更新:我已经能够通过添加来规避错误

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

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

4

4 回答 4

1

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

有几种可能的解决方案,最好的方法是为您的页面使用专用的 ViewModel。第二个是将您的实体类修改int IDint? ID,因此 Model-binder 将不需要指定项目,第三个选项是ID在调用之前清除与成员相关的任何错误的模型状态字典ModelState.IsValid

请注意,如果您继续使用实体类作为视图模型,您将可能受到 Mass Assignment 攻击(就像您的代码当前一样)。这就是为什么专用的 per-view ViewModel 是最好的。

于 2013-06-03T21:26:35.333 回答
1

正如 Dai 所说,推荐的方法是不要直接在视图中使用实体。造成这种情况的原因有很多,但是您现在正在体验它们。

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

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

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

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

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

@Html.HiddenFor(x => x.ID)
于 2013-06-03T22:21:37.153 回答
0

刚遇到这个问题,不知道和你一样

我对新建和编辑使用相同的页面,所以我有类似的东西:

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

但这仅对编辑有用,因此我添加了以下内容:

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

并且 ModelState.IsValid 现在是 true

于 2014-10-17T04:30:46.683 回答
0

如果将来有人遇到这种情况,这可能不是您想听到的答案,但这是我最终要做的。

我切换到使用显式实体框架(数据库优先)而不是使用代码优先。这重新生成了我的模型并随后解决了我的问题。我不确定为什么要修复它,但正如我在问题描述中所说,我认为这可能是我最初不小心更改的次要设置或代码行。

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

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

于 2013-06-04T15:35:08.697 回答